Подсчитайте количество вхождений определенного числа перед каждой строкой в ​​linux

У меня есть этот файл:

90 1 120 1 Transition 150 1 Transition 165 1 Transition 180 1 225 1 240 1 255 1 270 1 Transition 285 1 Transition 

и я хочу этот вывод:

 1 2 2 1 3 1 4 5 5 1 

Это означает, что 1 во втором столбце приходит 2 раза до 1-го перехода. Как это сделать, используя awk / grep?

Если вы хотите подсчитать количество раз 1 во втором поле до / между каждой строкой, в которой говорится, что Transition можно использовать awk как

 awk '$2 == "1" {count++;} /Transition/ {t_count++; print t_count "\t" count; count=0;}' <input file> 

который будет увеличивать счетчик каждый раз, когда 1 находится в поле 2, и каждый раз, когда линия соответствует Transition будет печататься счетчик количества строк перехода, за которым следует счет 1 строки.

Мой вывод из вашего входного файла:

 1 2 2 1 3 1 4 5 5 1 

Вот решение Perl, использующее тот же подход, что и ответ Эрика Ренуфа :

 $ perl -lane '$F[1]==1 && $c++; if(/Transition/){$k++; print "$k\t$c"; $c=0}' file 1 2 2 1 3 1 4 5 5 1 

объяснение

  • -l добавляет новую строку для каждого вызова print ;
  • -a включает «awk-mode», разбивая каждую входную строку на массив @F так, что $F[0] является первым полем, а $F[1] – вторым.
  • -ne сообщает perl обрабатывать свой входной файл по строкам и применять скрипт, заданный -e для каждой строки.
  • $F[1]==1 && $c++; : приращение $c на 1, если второе поле равно 1 .
  • if(/Transition/){$k++; print "$k\t$c"; $c=0}' if(/Transition/){$k++; print "$k\t$c"; $c=0}' : если эта строка соответствует Transition , приращение $k на единицу, напечатайте текущие значения $k и $c и установите $c обратно на 0.

Существуют ли другие строки, кроме «Переход» и «число, за которым следует 1»? Предполагаю, что нет. Что происходит, когда есть два перехода, между которыми нет ничего? Я предполагаю, что этого не произойдет.

Вы специально запрашиваете awk, и поэтому ответ Эрика идеален. Для полноты я хотел бы представить версию без awk 🙂

 | sed 's/.* 1 *$/CountThisLine/' | uniq -c | sed -n 's/CountThisLine//p' | nl -nln 

Первый sed выбирает строки, которые вы хотите подсчитать, и делает их одинаковыми, сохраняя переходы, uniq -c подсчитывает одинаковые последовательные строки, второй sed поддерживает только строки без перехода, а nl – результат.

 $ cat test.txt \ | sed 's/.* 1 *$/CountThisLine/' \ | uniq -c \ | sed -n 's/CountThisLine//p' \ | nl -nln 1 2 2 1 3 1 4 5 5 1