正则表达式中的问号

xra*_*alf 38 regex regex-greedy

我正在阅读正则表达式参考,我正在考虑?和?? 字符.你能用一些例子向我解释一下它们的用处吗?我不够了解他们.

谢谢

Jus*_*gan 34

这是一个很好的问题,我花了一段时间才看到懒惰??量词的意义.

? - 可选(贪婪)量词

有用的东西?很容易理解.如果你想找到既httphttps,你可以使用这样的模式:

https?
Run Code Online (Sandbox Code Playgroud)

此模式将匹配两个输入,因为它使s可选.

?? - 可选(懒惰)量词

??更微妙.它通常做同样的事情?.当你问:"这个输入是否满足这个正则表达式时,它不会改变真/假结果?" 相反,它与问题相关:"此输入的哪一部分与此正则表达式匹配,哪些部分属于哪些组?" 如果输入可以以多种方式满足模式,则引擎将根据?vs. ??(或*vs. *?+vs. +?)决定如何对其进行分组.

假设您有一组要验证和解析的输入.这是一个(公认的愚蠢)例子:

Input:       
http123
https456
httpsomething

Expected result:
Pass/Fail  Group 1   Group 2
Pass       http      123
Pass       https     456
Pass       http      something
Run Code Online (Sandbox Code Playgroud)

您尝试想到,这是第一件事,:

^(http)([a-z\d]+)$
Run Code Online (Sandbox Code Playgroud)
Pass/Fail  Group 1   Group 2    Grouped correctly?
Pass       http      123        Yes
Pass       http      s456       No
Pass       http      something  Yes
Run Code Online (Sandbox Code Playgroud)

它们都通过了,但你不能使用第二组结果,因为你只想要456在第2组中.

好的,让我们再试一次.假设第2组可以是字母或数字,但不是两者:

(https?)([a-z]+|\d+)
Run Code Online (Sandbox Code Playgroud)
Pass/Fail  Group 1   Group 2   Grouped correctly?
Pass       http      123       Yes
Pass       https     456       Yes
Pass       https     omething  No
Run Code Online (Sandbox Code Playgroud)

现在第二个输入很好,但是第三个输入被分组错误,因为?默认情况下是贪婪的(+也是,但是?先来了).在决定是否将s是部分https?或者[a-z]+|\d+,如果结果是合格无论哪种方式,正则表达式引擎始终会选择左边的一个.所以第2组输了,s因为第1组吸了它.

为了解决这个问题,你做了一个微小的改变:

(https??)([a-z]+|\d+)$
Run Code Online (Sandbox Code Playgroud)
Pass/Fail  Group 1   Group 2    Grouped correctly?
Pass       http      123        Yes
Pass       https     456        Yes
Pass       http      something  Yes
Run Code Online (Sandbox Code Playgroud)

从本质上讲,这意味着:"匹配,https如果你必须,但看看当组1正好时这是否仍然通过http." 引擎意识到它s可以作为一部分工作[a-z]+|\d+,因此它更喜欢将它放入第2组.


sem*_*ros 34

之间的主要区别???关系他们的懒惰.??是懒惰,?不是.

假设您想在文本正文中搜索"car"这个词,但您不希望仅限于单一的"汽车"; 你也希望与复数"汽车"相匹配.

这是一个例句:

I own three cars.

现在,如果我想匹配单词"car" 并且我只想获得字符串"car"作为回报,我会??像这样使用懒惰:

cars??

这就是说,"寻找汽车或汽车这个词;如果你发现任何一个,car那就回来了".

现在,如果我想匹配相同的单词("汽车"或"汽车")并且我希望得到整个比赛作为回报,我会?像这样使用非懒惰:

cars?

这就是说,"寻找汽车或汽车这两个词,无论你发现什么,都要归还汽车或汽车".

在计算机编程领域,懒惰通常意味着"仅根据需要进行评估".所以懒惰??只返回进行匹配所需的数量; 因为"汽车"中的"s"是可选的,所以不要退货.另一方面,非惰性(有时称为贪婪)操作尽可能地进行评估,因此?返回所有匹配,包括可选的"s".

就个人而言,我发现自己使用它?作为一种方式使其他正则表达式运算符变得懒惰(比如*+运算符)比我用它来简单的字符选项,但YMMV.

在Code中看到它

以上是在Clojure中实现的例子:

(re-find #"cars??" "I own three cars.")
;=> "car"

(re-find #"cars?" "I own three cars.")
;=> "cars"
Run Code Online (Sandbox Code Playgroud)

该项re-find是一个函数,它将第一个参数作为正则表达式,#"cars??"并返回它在第二个参数中找到的第一个匹配项"I own three cars."

  • 您的 `cars??` 示例是正确的,但它返回的结果与您只使用了 `car` 时的结果相同。您可能需要一个不同的示例来演示 ?? 的用处。 (3认同)
  • @VaradBhatnagar您需要转义正则表达式中的“?”字符。举个 Clojure 中的例子,如果你想匹配字符串 `foo?`,你可以使用 `(re-find #"foo\?" "foo?")`,其中 `\?` 转义了正则表达式中的问号。表达式,以便按字面意思处理它,而不是作为正则表达式运算符。 (2认同)

Mat*_*hen 11

? 只需使前一项(字符,字符类,组)可选:

colou?r
Run Code Online (Sandbox Code Playgroud)

匹配"颜色"和"颜色"

(swimming )?pool
Run Code Online (Sandbox Code Playgroud)

匹配"游泳池"和"游泳池"

??是相同的,但它也是懒惰的,所以如果可能的话,项目被排除.正如那些文件所指出的那样,?? 在实践中很少见.我从来没用过它.


Ram*_*asi 9

正则表达式中的其他一些问号用法

除了在其他答案中解释的内容之外,正则表达式中还有3个问号用途.    

  1. 否定前瞻

    如果你想要匹配其他东西不匹配的东西,则使用否定前瞻.负前瞻构造是一对括号,左括号后跟一个问号和一个感叹号.x(?!x2)

  2. 积极前瞻

    积极的前瞻工作方式也是如此.q(?=u)匹配a q后面紧跟a u,而不是u匹配的一部分.积极的先行构造是一对括号,左括号后跟一个问号和一个等号.

  3. 非捕获组

    无论何时在括号中放置正则表达式(),它们都会创建一个编号的捕获组.它将正则表达式中与正则表达式部分匹配的字符串部分存储在括号内.

    如果您不需要该组捕获其匹配项,则可以将此正则表达式优化为

    (?:Value)
    
    Run Code Online (Sandbox Code Playgroud)

另见这个这个.