Вивести друк тільки після знаходження шаблону


13

Існує сценарій (назвемо його echoer), який друкує на екрані купу інформації. Мені хотілося б бачити рядки лише після того, як знайдеться візерунок.

Я уявляю використання рішення, щоб виглядати щось подібне

echoer | solution_command <pattern>

В ідеалі patternце був би регулярний вираз, але для мене було б достатньо рядків з твердим значенням.


Тож візерунком може бути кілька рядків?
Inian

Глобус? Ви маєте на увазі регулярний вираз? Глобус має сенс лише для розширень імен файлів.
тердон

@Inian Я не впевнений, що розумію питання. Ви хочете сказати, чи хочу я, щоб це працювало з диз'юнкціями?
user23146

Відповіді:


21

AWK може це зробити за допомогою діапазонів шаблонів, що дозволяє використовувати будь-який регулярний вираз:

echoer | awk '/pattern/,0'

буде друкувати echoerвихід, починаючи з відповідності першого рядка pattern.

AWK заснований на шаблоні і зазвичай використовується з типом підходу "якщо ця модель відповідає, зробіть це". "Цей візерунок" може представляти собою діапазон шаблонів, визначений як "коли цей зразок збігається, починайте це робити, поки цей інший візерунок не збігається"; це визначається, записавши два шаблони, розділені комою, як вище. Шаблони можуть бути текстовими збігами, як у /pattern/, де поточний рядок перевіряється на зразок, інтерпретується як регулярний вираз; вони також можуть бути загальними виразами, оціненими для кожного рядка та вважатись відповідними, якщо їх результат не нульовий або не порожній.

У AWK типовою дією є друк поточного рядка.

Збираючи все це разом, awk '/pattern/,0'шукає відповідність рядків pattern, і як тільки він знайде його, застосовує дію за замовчуванням до всіх рядків, поки 0умова не збігається (не дорівнює нулю). awk '/pattern/,""'працював би теж.

Посібник Gawk детальніше описується.


3
Мені не було відомо про семантику діапазону з нулем як кінець діапазону. Спасибі!
Kusalananda

@StephenKitt Це чудово! Що робити, якщо я хотів надрукувати, поки він не збігався 0? Було б /pattern/,/0/? Як виглядатиме відповідь, як явно виписати дію за замовчуванням?
user23146

@ user23146 так, /pattern/,/0/друкується, поки не знайде рядок (запис), що містить "0". Написання фрагмента у відповідь з явною дією дає /pattern/,0 { print $0 }або рівнозначно /pattern/,0 { print }.
Стівен Кітт

7

Обов’язковий sedеквівалент одного @ StephenKitt awk:

sed '/pattern/,$!d'

patternтрактується як базовий регулярний вираз, як у grep(на відміну від розширеного регулярного вираження в awk/ egrep/ grep -E). У деяких sedреалізаціях є -E(BSD, ast, нещодавній GNU / busybox, незабаром POSIX) або -r(GNU, ssed, busybox, деякий останній BSD), щоб зробити це замість цього розширеними регулярними виразами, а деякі мають -P(ast) або -R(ssed), щоб зробити це перл-подібний регулярний вираз.

З perl:

perl -ne 'print if /pattern/ .. undef'

4

з GNU та * BSD grep:

grep -A1000000000 pattern file

Якщо у вашому файлі більше 1М рядків, це все.


0

Якщо ви використовуєте пейджер, наприклад, lessдля перегляду виводу з команди

less +pattern

0

awk для рядків після (але не включаючи) першого збігу шаблонів

Якщо рядок, що містить шаблон тригера, є еквівалентом "CUT ТУТ", ви можете опустити його з друкованого виводу:

echoer | awk 'flag ; /pattern/ { flag=1 }'

Кожен рядок вводу проходить через два компоненти в коді awk. Перший компонент - це те flag, що awk трактує як "друкувати рядок, якщо змінна flagне нульова". Оскільки змінні awk за замовчуванням дорівнюють 0, це спочатку нічого не надрукує.

Другий компонент /pattern/ { flag=1 }встановлює прапор на 1, як тільки він виявляє візерунок, і прапор зберігає це значення для решти пробігу.

До моменту вперше виявлення шаблону можливість друкувати цей рядок введення вже пройшла. Будь-які наступні рядки (включаючи додаткові рядки, що містять візерунок) будуть надруковані.


0

Баш

Трохи незграбний, але це працює.

#!/bin/bash
found=false
while IFS= read -r; do
    if $found || [[ $REPLY =~ pattern ]]; then
        found=true
        printf '%s\n' "$REPLY"
    fi
done

Ця версія покладається на cat, але її легше зрозуміти.

#!/bin/bash
while IFS= read -r; do
    if [[ $REPLY =~ pattern ]]; then
        printf '%s\n' "$REPLY"
        break
    fi
done
cat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.