如何在grep中进行非贪婪的比赛?

时间:2010-06-12 04:44:00

标签: regex shell command-line grep regex-greedy

我想要最短的比赛,模式应该是这样的:

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

...表示任何字符,输入是多行。

7 个答案:

答案 0 :(得分:233)

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

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

答案 1 :(得分:79)

Actualy .*?仅适用于perl。我不确定等效的grep扩展regexp语法是什么。幸运的是,您可以使用grep的perl语法,因此grep -P可以正常工作,但与grep -E相同的egrep将不起作用(这将是贪婪的)。

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

答案 2 :(得分:10)

grep

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

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

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

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

答案 3 :(得分:9)

我的grep在尝试了这个帖子中的东西之后有效:

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

确保为每一行添加空格

(我的是逐行搜索以吐出单词)

答案 4 :(得分:1)

对不起,我迟到了9年,但这可能会在2020年使观众受益。

因此,假设您有一行"Hello my name is Jello"。 现在,您要查找以'H'开头和以'o'结尾的单词,中间包含任意数量的字符。而且我们不想要线条,我们只想要单词。为此,我们可以使用表达式:

grep "H[^ ]*o" file

这将返回所有单词。这样做的方式是:允许所有字符代替中间的空格,这样就可以避免同一行中出现多个单词。

现在,您可以将空格字符替换为所需的任何其他字符。 假设第一行是"Hello-my-name-is-Jello",则可以使用以下表达式获取单词:

grep "H[^-]*o" file

答案 5 :(得分:0)

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

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

答案 6 :(得分:-1)

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

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