我正在阅读regular expressions reference而我在想什么?和??字符。你能用一些例子向我解释一下它们的用处吗?我不太了解他们。
谢谢
答案 0 :(得分:30)
这是一个很好的问题,我花了一段时间才看到懒惰??
量词的意义。
?
的用处很容易理解。如果您想同时找到http
和https
,可以使用这样的模式:
https?
此模式将匹配两个输入,因为它使s
可选。
??
更加微妙。它通常做同样的事情?
。当您询问时,它不会更改真/假结果:“此输入是否满足此正则表达式?”相反,它与问题相关:“此输入的哪一部分与此正则表达式匹配哪些部分属于哪些组?“如果输入可以多种方式满足模式,则引擎将根据?
与??
决定如何对其进行分组(或*
与*?
,或+
与+?
)。
假设您有一组要验证和解析的输入。这是一个(公认的愚蠢)例子:
Input:
http123
https456
httpsomething
Expected result:
Pass/Fail Group 1 Group 2
Pass http 123
Pass https 456
Pass http something
您尝试了第一件事,即this:
^(http)([a-z\d]+)$
Pass/Fail Group 1 Group 2 Grouped correctly?
Pass http 123 Yes
Pass http s456 No
Pass http something Yes
它们全部通过,但您无法使用第二组结果,因为您只想在第2组中使用456
。
好的,让我们try again。假设第2组可以是字母或数字,但不是两者:
(https?)([a-z]+|\d+)
Pass/Fail Group 1 Group 2 Grouped correctly?
Pass http 123 Yes
Pass https 456 Yes
Pass https omething No
现在第二个输入正常,但第三个输入错误,因为默认情况下?
是贪婪的(+
也是如此,但?
排在第一位)。在确定s
是https?
还是[a-z]+|\d+
的一部分时,如果结果是通过任何一种方式,正则表达式引擎将始终选择剩下。所以第2组失去s
,因为第1组吸了它。
要解决此问题,请制作one tiny change:
(https??)([a-z]+|\d+)$
Pass/Fail Group 1 Group 2 Grouped correctly?
Pass http 123 Yes
Pass https 456 Yes
Pass http something Yes
基本上,这意味着:“如果必须,请匹配https
,但是当第1组只是http
时,看看这是否仍然存在。”引擎意识到s
可以作为[a-z]+|\d+
的一部分,因此它更喜欢将其放入第2组。
答案 1 :(得分:30)
?
和??
之间的主要区别在于他们的懒惰。 ??
是懒惰的,?
不是。
假设您想在文本正文中搜索“car”这个词,但您不希望仅限于单一的“汽车”;你也希望与复数“汽车”相匹配。
这是一个例句:
I own three cars.
现在,如果我想匹配单词“car”并且我只想获得字符串“car”作为回报,我会像这样使用懒惰的??
:< / p>
cars??
这就是说,“寻找汽车或汽车这个词;如果你找到了,请返回car
而不再”。
现在,如果我想匹配相同的单词(“car”或“cars”)并且我希望得到整个匹配,我会使用非懒惰的{ {1}}喜欢这样:
?
这就是说,“寻找汽车或汽车这个词,无论你发现什么,都要回车或汽车。”
在计算机编程领域,懒惰通常意味着“仅根据需要进行评估”。所以懒惰的cars?
只返回匹配所需的数量;因为“汽车”中的“s”是可选的,所以不要退货。另一方面,非惰性(有时称为 greedy )操作尽可能地进行评估,因此??
返回所有匹配,包括可选的“s”。
就我个人而言,我发现自己使用?
作为使其他正则表达式运算符变得懒惰的方式(比如?
和*
运算符)比我用于简单字符选项更常见,但是YMMV。
以上是以Clojure为例的实现:
+
项(re-find #"cars??" "I own three cars.")
;=> "car"
(re-find #"cars?" "I own three cars.")
;=> "cars"
是一个函数,它将第一个参数作为正则表达式re-find
,并返回它在第二个参数中找到的第一个匹配#"cars??"
答案 2 :(得分:11)
?
只是使前一项(字符,字符类,组)可选:
colou?r
匹配“颜色”和“颜色”
(swimming )?pool
匹配“游泳池”和“游泳池”
??
是相同的,但它也是懒惰的,所以如果可能的话, 项将被排除。正如那些文件所指出的那样,??在实践中很少见。我从来没有用过它。
答案 3 :(得分:8)
除了在其他答案中解释的内容之外,在正则表达式中还有3个问号用途。
否定前瞻
如果您愿意,可以使用否定前瞻
匹配的东西没有其他东西。否定的
lookahead构造是一对括号,带有开口
括号后跟一个问号和一个感叹号。 x(?!x2)
示例
There
现在,默认情况下,RegEx e
会在字e
中找到第三个字母There
。
There
^
但是,如果您不希望e
紧跟r
,那么您可以使用RegEx e(?!r)
。现在的结果将是:
There
^
积极前瞻
积极前瞻的作用是一样的。 q(?=u)
与q
匹配
紧接着是u
,而不是u
部分
比赛。积极的先行构造是一对括号,
用左括号后跟一个问号和一个
等于。
示例
getting
现在,默认情况下,RegEx t
会在字t
中找到第三个字母getting
。
getting
^
但是,如果您希望t
紧跟i
,那么您可以使用RegEx t(?=i)
。现在的结果将是:
getting
^
非捕获群组
每当你在括号()
中放置正则表达式时,它们就会出现
创建一个编号的捕获组。它存储字符串的一部分
匹配的是正则表达式中的部分
括号中。
如果您不需要该组捕获其匹配项,则可以进行优化 这个正则表达式进入
(?:Value)
答案 4 :(得分:1)
在Oracle文档中使用“(一次或根本不)匹配” AutoMapper
勉强量词运行测试工具表明,它可以保证始终为空。
X??
https://docs.oracle.com/javase/tutorial/essential/regex/quant.html
似乎与空匹配项相同。
$ java RegexTestHarness
Enter your regex: x?
Enter input string to search: xx
I found the text "x" starting at index 0 and ending at index 1.
I found the text "x" starting at index 1 and ending at index 2.
I found the text "" starting at index 2 and ending at index 2.
Enter your regex: x??
Enter input string to search: xx
I found the text "" starting at index 0 and ending at index 0.
I found the text "" starting at index 1 and ending at index 1.
I found the text "" starting at index 2 and ending at index 2.