Как сделать не жадные совпадения в grep? - PullRequest
153 голосов
/ 12 июня 2010

Я хочу получить кратчайшее совпадение, и шаблон должен выглядеть примерно так:

<car ... model=BMW ...>
...
...
...
</car>

... означает любой символ и ввод состоит из нескольких строк.

Ответы [ 5 ]

242 голосов
/ 12 июня 2010

Вы ищете не жадный (или ленивый) матч. Чтобы получить не жадное совпадение в регулярных выражениях, вам нужно использовать модификатор ? после квантификатора. Например, вы можете изменить .* на .*?.

По умолчанию grep не поддерживает не жадные модификаторы, но вы можете использовать grep -P для использования синтаксиса Perl.

79 голосов
/ 25 апреля 2011

На самом деле .*? работает только в perl.Я не уверен, каков будет эквивалентный синтаксис расширенного регулярного выражения grep.К счастью, вы можете использовать синтаксис perl с grep, так что grep -P будет работать, но grep -E, который совпадает с egrep, не будет работать (будет жадным).

См. Также: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html

10 голосов
/ 08 мая 2015

grep

Для не жадного совпадения в grep вы можете использовать отрицательный класс символов. Другими словами, старайтесь избегать подстановочных знаков.

Например, чтобы извлечь все ссылки на файлы JPEG из содержимого страницы, вы должны использовать:

grep -o '"[^" ]\+.jpg"'

Для работы с несколькими строками сначала проложите ввод через xargs. Для производительности используйте ripgrep.

9 голосов
/ 27 сентября 2012

Мой grep, который работает после пробной работы в этой теме:

echo "hi how are you " | grep -shoP ".*? "

Просто убедитесь, что вы добавляете пробел к каждой из ваших строк

(Мой был построчным поиском, чтобы выплевывать слова)

0 голосов
/ 13 сентября 2013

Краткий ответ использует следующее регулярное выражение:

(?s)<car .*? model=BMW .*?>.*?</car>
  • (? S) - это соответствует многострочному
  • . *? - соответствует любому персонажу несколько раз ленивым образом (минимально матч)

(немного) более сложный ответ:

(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>

Это позволит сопоставить car1 и car2 в следующем тексте

<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
  • (..) представляет группу захвата
  • \ 1 в этом контексте соответствует тому же тексту, что и последний найденный группа захвата номер 1
...