Подсчет строк между «X»

13

Я хочу посчитать строки между "X". Это всего лишь пример; Я должен применить код для сложного биологического результата. Я буду благодарен, если вы можете предложить какую-либо команду, желательно с использованием awk, grepили, sedкак я знаком с ними.

Пример:

X
Y
Y
Y
X
Y
Y
Y
Y
X
Y
X

Желаемый результат:

3
4
1
Рея
источник
2
Возможно, вас заинтересует биоинформатика, если вы будете работать в этой области.
Тердон

Ответы:

13

С awk:

$ awk '!/X/{count++}/X/{print count; count = 0}' input

3
4
1

Увеличить счетчик для каждой строки, не содержащей X; распечатать и сбросить счетчик для строк, содержащих X.

Мур
источник
2
Если первая строка не была X, первое число строк будет по-прежнему считаться и выводиться с этим решением, пока первая строка с не Xбудет сопоставлена. EX (Невозможно добавить новые строки в комментариях, но Y X Y Y X Y Y Y1 2
Dan
1
@muru это не сработает, если в конце не было X (нужно добавить END{if (count)print count}), и при создании пустой строки, где X был в начале, чтобы избежать, вы также можете добавить /X/&&countв условии
αғsнιη
1
Хех. Один комментарий жалуется, что ведущие Ys не должны учитываться, потому что они не находятся точно между двумя Xs; другой жалуется, что конечные Ys не учитываются, потому что они не находятся точно между двумя Xs. Я подожду, пока ОП уточнит, если нужно; Я в порядке с этим ответом, как это до тех пор.
Муру
12
$ awk '/X/ && prev{print NR-prev-1} /X/{prev=NR}' file
3
4
1

Как это устроено:

Awk неявно читает входные файлы построчно.

  • /X/ && prev{print NR-prev-1}

    Для любой строки, которая содержит Xи если мы ранее присвоили значение prev, выведите номер текущей строки NR, минус prevминус один.

  • /X/{prev=NR}

    Для любой строки, содержащей X, установить переменную prevдля текущего номера строки, NR.

John1024
источник
4
Да, хорошо. Злоупотребление NRдает мне представление:awk '/X/{print NR - 1; NR = 0}' foo
Муру
Спасибо, это дает мне точную информацию. что требуется.
Рея
Муро: Хорошо и сложно. За исключением печати одного значения слишком много, оно работает для меня под gawk и mawk. Мне любопытно, является ли это гарантированным поведением. @EdMorton?
John1024
3
@rhea Если ваша первая строка не всегда есть X, есть небольшая разница в выводе между двумя ответами, как я объяснил в комментарии к ответу Муру.
Дэн
1
@ John1024 спасибо! Я надеюсь, что это поможет мне.
Рея
6

Другой простой awkподход, который работает с образцами данных OP, и если Xон не был в первом или даже в последнем или повторном X.

awk -v RS='X' 'NF{print NF}' infile

Выше указано правильное значение, если в каждой строке имеется только одно поле с FS по умолчанию для любых пробелов , в противном случае ниже пересматривается в общем случае для подсчета линий . Вы можете ввести свой ШАБЛОН вместо X там.

awk -F'\n' -v RS='X' 'NF>2{print NF-2}'

Пример ввода:

X
Y YYY Y
YY
YY Y YY YY Y Y
X
Y Y Y
X
Y
Y
X
X

Выход:

3
1
2
αғsнιη
источник
1

Большинство ответов здесь соответствуют содержанию строки, которая будет подсчитана с использованием регулярных выражений, встроенных в программу Awk. Если вам нужно сопоставить строки с содержимым, которое может содержать специальные символы (либо в Awk, либо в регулярных выражениях), было бы лучше на самом деле сравнить строки на равенство. Поэтому я предлагаю следующий сценарий Awk как вариант ответа Муру :

BEGIN {
    count = 0;
}

{
    if ($0 == needle) {
        if (count) {
            print count;
            count = 0;
        }
    } else {
        count++;
    }
}

Сохраните его как текстовый файл, например count-rows.awk, и вызовите его следующим образом:

awk -f count-rows.awk -v needle=X input

Вы можете настроить значение needleпо своему вкусу. Преимущество этого метода в том, что вы можете вызывать программу из сценария оболочки с произвольным значением, чтобы needleизбежать проблем:

awk -f count-rows.awk -v needle="$needle" input
Дэвид Фёрстер
источник