
Допустим, у меня есть следующий файл:
$ cat test
test line 1
test line 2
line without the search word
another line without it
test line 3 with two test words
test line 4
По умолчанию grep
возвращает каждую строку, содержащую поисковый запрос:
$ grep test test
test line 1
test line 2
test line 3 with two test words
test line 4
Передача --color
параметра grep
заставит его выделить часть строки, которая соответствует выражению поиска, но он по-прежнему возвращает только строки, содержащие выражение. Есть ли способ вывести grep
каждую строку в исходном файле, но выделить совпадения?
Мой текущий ужасный хак для достижения этой цели (по крайней мере для файлов, в которых нет более 10000 последовательных строк без совпадений) выглядит так:
$ grep -B 9999 -A 9999 test test
Если grep
это не удается, есть ли другой инструмент командной строки, который предлагает ту же функциональность? Я возился сack
, но, похоже, и для этого нет возможности.
решение1
grep --color -E "test|$" yourfile
То, что мы здесь делаем, это сопоставление с шаблоном $
, а тестовый шаблон, очевидно, $
не имеет ничего для раскрашивания, поэтому только тестовый шаблон получает цвет. -E
Просто включается расширенное сопоставление регулярных выражений.
Вы можете легко создать из этого функцию, например, такую:
highlight () { grep --color -E "$1|$" "${@:1}" ; }
решение2
ack --passthru --color string file
для Ubuntu и Debian используйте ack-grep вместо ack
ack-grep --passthru --color string file
решение3
Другой способ сделать этоправильноипортативнос grep
(помимо использования двух регулярных выражений с чередованием, как в принятом ответе) осуществляется через шаблон null (и соответственно строку null).
Он должен работать одинаково хорошо с обоими -E
и -F
переключателями, поскольку,по стандарту:
-E
Match using extended regular expressions.
[...] A null ERE shall match every line.
и
-F
Match using fixed strings.
[...] A null string shall match every line.
Так что это просто вопрос бега
grep -E -e '' -e 'pattern' infile
и соответственно
grep -F -e '' -e 'string' infile
решение4
ripgrep
Используйте ripgrep
с его --passthru
параметром:
rg --passthru pattern file.txt
Это один изсамые быстрые инструменты поиска, так как он построен на основеРегулярный движок Rustкоторый использует конечные автоматы, SIMD и агрессивные литеральные оптимизации, чтобы сделать поиск очень быстрым.
--passthru
- Распечатать как совпадающие, так и несовпадающие строки.Другой способ добиться похожего эффекта — изменить шаблон так, чтобы он соответствовал пустой строке. Например, если вы ищете с помощью ,
rg foo
то использованиеrg "^|foo"
вместо этого выведет каждую строку в каждом искомом файле, но будут выделены только вхождения foo. Этот флаг включает то же поведение без необходимости изменять шаблон.