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


13

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

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

echoer | solution_command <pattern>

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


Так шаблон может быть несколько строк?
Иньан

Глобус? Вы имеете в виду регулярное выражение? Глобусы имеют смысл только для расширений имен файлов.
Тердон

@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 млн строк, вот и все.


0

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

less +pattern

0

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

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

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.