Я хочу, чтобы grep самое короткое совпадение, и шаблон должен выглядеть примерно так:
<car ... model=BMW ...>
...
...
...
</car>
... означает любой символ, а вход - несколько строк.
Я хочу, чтобы grep самое короткое совпадение, и шаблон должен выглядеть примерно так:
<car ... model=BMW ...>
...
...
...
</car>
... означает любой символ, а вход - несколько строк.
Вы ищете не-жадное (или ленивое) совпадение. Чтобы получить не-жадное соответствие в регулярных выражениях, вам нужно использовать модификатор ?
после квантификатора. Например, вы можете изменить .*
на .*?
.
По умолчанию grep
не поддерживает нежелательные модификаторы, но вы можете использовать grep -P
для использования синтаксиса Perl.
Фактически .*?
работает только в perl
. Я не уверен, какой эквивалентный синтаксис расширенного регулярного выражения grep будет. К счастью, вы можете использовать синтаксис perl с grep, поэтому grep -P
будет работать, но grep -E
, который будет таким же, как egrep
, не будет работать (это было бы жадно).
Смотрите также: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
Мой grep, который работает после тестирования материала в этом потоке:
echo "hi how are you " | grep -shoP ".*? "
Просто убедитесь, что вы добавили пробел к каждой из ваших линий
(Mine был строковым поиском, чтобы выплескивать слова)
Для не-жадного соответствия в grep
вы можете использовать отрицательный класс символов. Другими словами, попробуйте избежать подстановочных знаков.
Например, чтобы извлечь все ссылки на jpeg файлы из содержимого страницы, вы должны использовать:
grep -o '"[^" ]\+.jpg"'
В коротком ответе используется следующее регулярное выражение:
(?s)<car .*? model=BMW .*?>.*?</car>
A (немного) более сложный ответ:
(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
Это позволит сопоставить car1 и car2 в следующем тексте
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>