Regex 如何在grep中进行非贪婪匹配?

Regex 如何在grep中进行非贪婪匹配?,regex,shell,command-line,grep,regex-greedy,Regex,Shell,Command Line,Grep,Regex Greedy,我想grep最短匹配,模式应该是: <car ... model=BMW ...> ... ... ... </car> ... ... ... 。。。表示任意字符,输入为多行 您正在寻找一个不贪婪(或懒惰)的匹配。要在正则表达式中获得非贪婪匹配,需要在量词后面使用修饰符?。例如,您可以将*更改为*? 默认情况下,grep不支持非贪婪修饰符,但您可以使用grep-p来使用Perl语法。实际上,*?只在Perl中工作。我不确定等效的grep扩展regexp语法是什么。

我想grep最短匹配,模式应该是:

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

...
...
...

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

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


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

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


另请参见:

我的grep在尝试此线程中的内容后仍然有效:

echo "hi how are you " | grep -shoP ".*? "
只需确保在每一行中都添加一个空格


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

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

(?s)<car .*? model=BMW .*?>.*?</car>
grep "H[^ ]*o" file
grep "H[^-]*o" file
(?s)。*?
  • (?s)-这将跨多行进行匹配
  • *?-以惰性方式匹配任意字符多次(最小 比赛)
一个(稍微)复杂的答案是:

(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
(?s)。*?
这将使以下文本中的car1和car2匹配成为可能

<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>

...
...
...
...
...
...
  • (..)表示捕获组
  • \在此上下文中,1与最近由匹配的相同文本匹配 捕获组编号1
grep
对于
grep
中的非贪婪匹配,可以使用否定字符类。换句话说,尽量避免使用通配符

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

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

要处理多行,请首先通过
xargs
管道输入。对于性能,请使用。

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


对不起,我迟到了9年,但这可能对2020年的观众有用

因此,假设您有一行代码“你好,我的名字是果冻”。 现在,您需要查找以
'H'
开头,以
'o'
结尾的单词,中间有任意数量的字符。我们不需要台词,我们只需要文字。因此,我们可以使用以下表达式:

(?s)<car .*? model=BMW .*?>.*?</car>
grep "H[^ ]*o" file
grep "H[^-]*o" file
这将返回所有单词。其工作原理是:它将允许所有字符,而不是空格字符,这样我们可以避免在同一行中出现多个单词

现在,您可以使用所需的任何其他字符替换空格字符。 假设初始行是“你好,我的名字是Jello”,那么您可以使用以下表达式获取单词:

(?s)<car .*? model=BMW .*?>.*?</car>
grep "H[^ ]*o" file
grep "H[^-]*o" file

grep-P
在GNU grep 2.9中不起作用——只是尝试了一下(它没有错误,只是默默地不应用
。not类也不起作用,例如:
env | grep'[^\=]*\='
在Darwin/OSX 10.8 Mountain Lion中没有
grep-P
选项或
pgrep
命令,但是
egrep
非常有效。在我的OSX 10.9机器上有一个
pgrep
命令,但它是一个完全不同的程序,其目的是“按名称查找或发送进程信号”@Robertotomaás在这里回应了一个6年前的评论,但是……我也这么认为,然后意识到我得到了多个非贪婪的匹配。例如,在彩色终端上,你可以看到'echo“bbbbbbb”| grep-P'b.*b'`返回2个匹配。eegg:dot-all修饰符也被称为multiline。它是一个更改“.”的修饰符匹配行为以包括换行符(通常不会)。在grep中没有这样的修饰符,但在中有。更正:在大多数支持它的regex风格中,允许
匹配换行符的模式称为DOTALL或single-line模式;Ruby是唯一一种称之为multiline的模式。在其他风格中,multiline是允许锚定的模式(
^
$
)匹配行边界。Ruby没有等效的模式,因为在Ruby中它们总是这样工作。
-P
对我来说是一个全新的模式,多年来我一直在愉快地变大,而且只使用
-E
…浪费了这么多年!-自我提示:重新阅读手册页(甚至更多!)一般来说,你永远不会消化足够的开关和选项。在某些平台上(比如MacOSX)
grep
不支持
-P
,但是如果您使用
egrep
,您可以使用
*?
模式来实现相同的结果。
egrep-o'start.*.end'text.html
作为@SaltyNuts注释的扩展,Mac OS X不支持
-P
,但是
-E
将调用
egreped
*?
很好用。
-shoP
很好的记忆法:)
echo“bbbbb”| grep-shoP“b.*?b”
是一个小小的学习经历。唯一对我有效的方法就是显式懒惰。你在2020年救了我,谢谢!