grep --before-context 5 показывает 5 строк перед матчем.
Я хочу показать все перед матчем.
Делать grep --before-context 99999999будет работать, но это не очень ... профессионально.
Как показать все файлы до матча?
grep --before-context 5 показывает 5 строк перед матчем.
Я хочу показать все перед матчем.
Делать grep --before-context 99999999будет работать, но это не очень ... профессионально.
Как показать все файлы до матча?
Ответы:
Сед лучше для этого.
Просто сделать:
sed '/PATTERN/q' FILE
Это работает так:
Для каждой строки мы посмотрим, соответствует ли она /PATTERN:
Это наиболее эффективное решение, потому что, как только оно видит PATTERN, оно выходит. Без q, sed продолжит читать остальную часть файла и ничего с этим не делать. Для больших файлов это может иметь значение.
Этот трюк также можно использовать для эмуляции head:
sed 10q FILE
sed '/PATTERN/Q' FILEпропустит согласованную строку. Qэто расширение GNU, поэтому оно не будет работать с любым sed.
sed может заменить большую часть функциональности grep.
sed -n '1,/<pattern>/ p' <file>
Это означает печать с первой строки до совпадения шаблона.
Пара примеров из диапазона
sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
распечатать до и включая матч:
awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename
распечатать до НО НЕ включая матч:
awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
Qэто круто, но гну конкретный afaik, sed -n '/pattern/!p;//q'будет более портативным.
!делает pприменить к линиям не совпадающих pattern, но потом //qменя смущает ...
//означает «предыдущее регулярное выражение» (я думал, что это означает «соответствовать пустой строке»). Я думаю , что более короткий вариант того же раствора: sed -n '/pattern/q;p?
Следующие grepметоды чистого GNU не эффективны.
Поиск всего до первого экземпляра строки " foo " в файловой строке , используя три grepс:
grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar
Соответствует до последнего экземпляра " foo ":
grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar
Примечание: подробности о последнем grepможно найти в: Regex (grep) для многострочного поиска .
grepс (+ pcre), когда нужно просто запустить один sedвызов: sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'??
sedкод, кажется, стоит своего ответа, или может быть добавлен к одному из других. Re 7 greps: Потому что не было grepответа ... (плюс, ответ помогает показать, почему нет.)
Добавляя к ответу Микеля выше ...
Для того, чтобы напечатать все строки до, но не включая , первую строчку в FILEсодержащем PATTERN, попробуйте:
sed '/.*PATTERN.*/{s///;q;}' FILEЭто соответствует всей строке, содержащей шаблон, заменяет ее пустой строкой, а затем завершает работу без обработки остальной части файла.
Пост-скрипт:
Самый простой / понятный способ предотвратить вывод дополнительной строки в конце (без использования другого инструмента) - это снова запустить sed и удалить новую заключительную строку:
sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'
... и так как мы сейчас удаляем эту строку, наша предыдущая работа избыточна, и мы можем упростить до:
sed '/PATTERN/q' FILE | sed '$d'
sedвызова.
tcshи в bashпсевдониме, мне нужно было убедиться, что я имел относительно сжатое однострочное решение, которое работало как в стандарте, так и в GNU sed(для переносимости); все требования, которые ваш вклад вполне может удовлетворить. Как человек, который использует sed очень редко, моим самым важным требованием было то, что я мог быстро понять, когда я хочу легко изменить или изменить его назначение через годы.
Для людей, которые предпочитают запоминать только основные инструменты в повседневной работе и готовы принять менее изящные и менее эффективные решения:
head -n $(grep -n pattern filename | cut -d: -f1) filename
Если эта команда предназначена для скрипта, я буду искать более элегантные (и, возможно, эффективные) решения. Если это одноразовая команда или сценарий выброса, мне все равно.
Вы также можете использовать один из следующих
tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac
или же
tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac
или же
tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac
Первый вариант очень похож на предложенный OP, только он обеспечивает отображение достаточного количества строк перед контекстом путем подсчета строк в файле.
Второй вариант ищет номер строки первого совпадения (вы также можете изменить это, изменив внутреннюю «голову»), а затем использует заголовок для этого номера.
Последний параметр заменяет все новые строки соответствием, а затем заменяет два соседних совпадения новой строкой. Результатом этого является строка для каждого блока текста между двумя совпадениями. После этого он использует 'head', чтобы выбрать совпадение первой строки (отрывать блок текста до первого совпадения), а затем переводит каждое совпадение в новую строку. эта опция работает, только если файл в следующем формате
pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern
texttexttext
texttexttexttexttexttexttexttexttext
и так далее
sedкоманда внизу довольно грубая.