Підрахунок ліній між "X" s


13

Я хочу порахувати рядки між "X" s. Це лише приклад; Я повинен застосувати код до складного біологічного результату. Я буду вдячний, якщо ви можете запропонувати якусь команду, бажано використовувати 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
Якщо перший рядок не був an X, перше число рядків все одно буде рахуватися і виводиться за допомогою цього рішення, поки перший рядок з не Xбуде збігатися. EX (Не можна додати нові рядки в коментарі, але врахуйте, що між кожним символом є новий рядок; P): Y X Y Y X Y Y Yбуде виводитися:1 2
Dan

1
@muru це не спрацює, якщо в кінці не було X (потрібно додати END{if (count)print count}), і створити порожній рядок, де X починався, щоб уникнути, ви можете також додати /X/&&countумову
αғsnιη

1
Хе. Один коментар скаржиться, що провідні Ys не слід рахувати, оскільки вони не перебувають між двома Xs; інший скаржиться на те, що проміжки Ys не враховуються, оскільки вони точно не між двома X. Я зачекаю, коли ОП уточнить, якщо потрібно; Я добре з цією відповіддю, як і до цього часу.
муру

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.


4
Ага, приємно. Зловживання NRдає мені думку:awk '/X/{print NR - 1; NR = 0}' foo
muru

Дякую, це дає мені точну інформацію. що потрібно.
Rhea

Муро: Приємно і хитро. За винятком того, що надрукувати одне значення занадто багато, воно працює для мене під гаук та маук. Мені цікаво, чи це гарантована поведінка. @EdMorton?
John1024

3
@rhea Якщо ваш перший рядок завжди є X, є невелика різниця у результатах між двома відповідями, як я пояснив у коментарі під відповіддю Муру.
Дан

1
@ John1024 дякую! Я сподіваюся, що це допоможе мені.
Rhea

6

Ще один простий awkпідхід, який працює на вибіркових даних ОП, і якщо Xвін не був у першій чи навіть в останній чи повторній X.

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

Вище вказано правильно, коли у кожному рядку є лише одне поле з умовними FS будь-якими пробілами , інакше нижче переглядається в загальному випадку для підрахунку лінійно . Ви можете ввести PATTERN замість 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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.