我在 SuperUser 上回答了这个问题,该问题与 grepping 输出时使用的正则表达式类型有关。
我给出的答案是这样的:
tail -f log | grep "some_string.*some_string"
然后,在对我的回答的三条评论中,@Bob写道:
.*
是贪婪的,可能会捕获比你想要的更多的东西。.*?
通常会更好。
那么这个,
the
?
是 上的修饰符*
,使其变得懒惰而不是贪婪的默认值。假设 PCRE。
我用谷歌搜索PCRE
,但在我的答案中无法理解这有什么意义?
最后这个,
我还应该指出,这是正则表达式(grep 默认执行 POSIX 正则表达式),而不是 shell glob。
我只知道 Regex 是什么以及它在 grep 命令中的基本用法。所以,我无法得到这 3 条评论中的任何一条,我有这些问题:
.*?
vs.的用法有什么区别.*
?- 哪个更好,在什么情况下?请提供例子。
也有助于理解评论,如果有人可以
更新:作为问题的答案Regex 与 Shell Globs 有何不同? @Kusalananda在他的评论中提供了这个链接。
注意:如果需要,请在回答参考上下文之前阅读我对此问题的回答。
假设我采用如下字符串:
can cats eat plants?
使用贪心
c.*s
将匹配整个字符串,因为它以 开头c
和结尾s
,作为一个贪心运算符,它会继续匹配直到最后出现 s。而使用惰性
c.*?s
只会匹配直到s
找到第一次出现,即 stringcan cats
。从上面的示例中,您可能能够收集到:
“贪婪”意味着匹配最长的可能字符串。“懒惰”意味着匹配最短的可能字符串。将 a 添加到, ,或
?
等量词后使其变得懒惰。*
+
?
{n,m}
Ashok 已经指出了和 之间的区别
.*
,.*?
所以我将提供一些额外的信息。grep
(假设是 GNU 版本)支持 4 种匹配字符串的方法:-F
选项-E
选项-P
GNU grep 中的选项grep
默认使用 BRE。BRE 和 ERE 记录在 POSIX 的正则表达式章节中,PCRE 记录在其官方网站中。请注意,功能和语法可能因实现而异。
值得一提的是,BRE 和 ERE 都不支持惰性:
因此,如果您想使用该功能,则需要改用 PCRE:
.*
用于匹配可能的“最长” 1模式。.*?
用于匹配可能的“最短” 1模式。根据我的经验,最想要的行为通常是第二个。
例如,假设我们有以下字符串,我们只想匹配 html 标签2,而不是它们之间的内容:
现在比较
.*
vs.*?
:1.正如 Kusalananda 指出的那样,正则表达式上下文中“最长”和“最短”的含义有点棘手。有关详细信息,请参阅官方文档。
2.不建议用正则解析html。这只是一个用于教育目的的示例,请勿在生产中使用它。
可以通过多种方式匹配字符串(从简单到复杂):
作为静态字符串(假设 var='Hello World!'):
外壳
[ "$var" = "Hello World!" ] && echo yes
grep
echo "$var" | grep -F "Hello"
bash
grep -F "Hello" <<<"$var"
作为一个整体:
shell
echo ./*
# 列出pwd 中的所有文件。
外壳
case $var in (*Worl*) echo yes;; (*) echo no;; esac
重击
[[ "$var" == *"Worl"* ]] && echo yes
有基本的和扩展的 glob。该
case
示例使用基本的 glob。bash[[
示例使用扩展的 glob。第一个文件匹配可以是基本的或在某些 shell 上扩展,例如extglob
在 bash 中设置。在这种情况下,两者是相同的。Grep 无法使用 glob。glob中的星号表示与正则表达式中的星号不同的含义:
glob
* matches any number (including none) of
任何字符。正则表达式
* matches any number (including none) of the
前面的元素。作为基本正则表达式(BRE):
sed
echo "$var" | sed 's/W.*d//'
#打印:你好!
grep
grep -o 'W.*d' <<<"$var"
#打印世界!
(基本)shell 或 awk 中没有 BRE。
扩展正则表达式 (ERE):
bash
[[ "$var" =~ (H.*l) ]]
# match: Hello Worl
sed
echo "$var" | sed -E 's/(d|o)//g'
# print: Hell Wrl!
awk
awk '/W.*d/{print $1}' <<<"$var"
# print: Hello
grep
grep -oE 'H.*l' <<<"$var"
# print: Hello Worl
Perl 兼容的正则表达式:
grep
grep -oP 'H.*?l
#打印:Hel
只有在 PCRE 中 a
*?
有一些特定的语法含义。它使星号变得懒惰(不贪婪):懒惰而不是贪婪。
这只是冰山一角,有贪婪的,有懒惰的,也有温顺的或占有欲的。还有lookahead 和lookbehind但这些不适用于星号
*
。有一种替代方法可以获得与非贪婪正则表达式相同的效果:
这个想法很简单:不要使用点
.
,否定下一个要匹配的字符[^o]
。使用网络标签:以上应该完全澄清所有@Bob 3 评论。释义:
.*
是贪心.*?
不是。问题
的用法有什么区别。? 与.. ?
.*?
仅在 PCRE 语法中有效。.*
更便携。[^a]*
哪个更好,在什么情况下?请提供例子。
更好的?这取决于目标。没有更好的了,每个都有不同的用途。我在上面提供了几个例子。你需要更多吗?