Вывод на печать только после нахождения шаблона

13

Есть сценарий (давайте назовем его echoer), который печатает на экране кучу информации. Я бы хотел видеть линии только после того, как шаблон найден.

Я представляю использование решения, чтобы выглядеть примерно так

echoer | solution_command <pattern>

В идеале patternбыло бы регулярным выражением, но для меня было бы достаточно строк с жесткими значениями.

user23146
источник
Так шаблон может быть несколько строк?
Иньан
Глобус? Вы имеете в виду регулярное выражение? Глобусы имеют смысл только для расширений имен файлов.
Тердон
@Inian Я не уверен, что понимаю вопрос. Вы хотите спросить, хочу ли я, чтобы это работало с дизъюнкциями?
user23146

Ответы:

21

AWK может сделать это с диапазонами шаблонов, что позволяет использовать любое регулярное выражение:

echoer | awk '/pattern/,0'

выведет echoerвывод, начиная с соответствия первой строки pattern.

AWK основан на шаблонах и обычно используется с подходом типа «если этот шаблон соответствует, сделайте это». «Этот шаблон» может быть диапазоном шаблонов, определяемых как «когда этот шаблон соответствует, начинайте делать это, пока этот другой шаблон не будет соответствовать»; это определяется записью двух шаблонов, разделенных запятой, как указано выше. Шаблоны могут быть текстовыми совпадениями, например /pattern/, если текущая строка сверяется с шаблоном, интерпретируемым как регулярное выражение; они также могут быть общими выражениями, вычисляться для каждой строки и считаться совпадающими, если их результат ненулевой или непустой.

В AWK действием по умолчанию является печать текущей строки.

Собрав все это вместе, awk '/pattern/,0'ищет совпадения строк patternи, как только он находит одну, применяет действие по умолчанию ко всем строкам до тех пор, пока 0условие не совпадет (не равно нулю). awk '/pattern/,""'будет работать тоже.

Руководство Gawk входит в гораздо более подробно.

Стивен Китт
источник
3
Я не знал о семантике диапазона с нулем как концом диапазона. Благодарность!
Кусалананда
@ StefhenKitt Это здорово! Что если я захочу распечатать, пока оно не совпадет 0? Это будет /pattern/,/0/? Как будет выглядеть ответ, явно выписывая действие по умолчанию?
user23146
@ user23146 да, /pattern/,/0/будет печатать, пока не найдет строку (запись), содержащую «0». Запись фрагмента в ответ с явным действием дает /pattern/,0 { print $0 }или эквивалентно /pattern/,0 { print }.
Стивен Китт
7

Обязательный sedэквивалент @ StephenKitt's 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:

perl -ne 'print if /pattern/ .. undef'
Стефан Шазелас
источник
4

с GNU и * BSD grep:

grep -A1000000000 pattern file

Если ваш файл не содержит более 1 млн строк, вот и все.

mosvy
источник
0

Если вы используете пейджер, например, lessдля просмотра выходных данных команды

less +pattern
Iruvar
источник
0

awk для строк после (но не включая) первого совпадения с образцом

Если строка, содержащая шаблон триггера, является эквивалентом «CUT HERE», вы можете опустить ее в выводе на печать:

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

Каждая строка ввода проходит через два компонента в коде awk. Первый компонент flag, который awk интерпретирует как «напечатать строку, если переменная flagотлична от нуля». Так как переменные awk по умолчанию равны 0, изначально ничего не печатается.

Второй компонент, /pattern/ { flag=1 }устанавливает флаг в 1, как только обнаруживает шаблон, и флаг сохраняет это значение до конца цикла.

К тому времени, когда шаблон впервые обнаружен, возможность распечатать эту строку ввода уже прошла. Любые последующие строки (включая дополнительные строки, содержащие шаблон) будут напечатаны.

Gaultheria
источник
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
wjandrea
источник