我想grep最短的匹配和模式应该是这样的:

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

... 表示任意字符且输入为多行。


当前回答

您正在寻找一个非贪婪(或懒惰)匹配。要在正则表达式中获得一个非贪婪匹配,您需要使用修饰符?在量词之后。例如,可以将。*改为。*?。

默认情况下,grep不支持非贪婪修饰符,但是可以使用grep -P来使用Perl语法。

其他回答

我知道这有点死帖,但我刚刚注意到这是有效的。它从我的输出中删除了清理和清理。

> grep -v -e 'clean\-\?up'
> grep --version grep (GNU grep) 2.20

grep

对于grep中的非贪婪匹配,您可以使用反字符类。换句话说,尽量避免使用通配符。

例如,要从页面内容中获取所有jpeg文件的链接,你可以使用:

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

要处理多行,首先通过xargs管道输入。为了提高性能,请使用ripgrep协议。

简单的回答是使用下一个正则表达式:

(?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号组

实际上。*?只在perl中工作。我不确定等效的grep扩展regexp语法是什么。幸运的是,您可以在grep中使用perl语法,因此grep -P可以工作,但与egrep相同的grep -E将无法工作(它将是贪婪的)。

参见:http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html

您正在寻找一个非贪婪(或懒惰)匹配。要在正则表达式中获得一个非贪婪匹配,您需要使用修饰符?在量词之后。例如,可以将。*改为。*?。

默认情况下,grep不支持非贪婪修饰符,但是可以使用grep -P来使用Perl语法。