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 grep
s: Потому что не было 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
команда внизу довольно грубая.