正则表达式中的问号

我在读 正则表达式引用,我在想什么?然后呢?角色。你能给我举几个例子说明它们的用处吗?我还不够了解他们。

谢谢你

102206 次浏览

?只是让前一项(字符、字符类、组)成为可选项:

colou?r

“颜色”和“颜色”匹配

(swimming )?pool

与“游泳池”和“游泳池”相匹配

??是相同的,但它也是惰性的,所以如果可能的话,应该排除 威尔项。就像那些医生说的那样?在实践中是罕见的。我从没用过。

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

可选(贪婪)量词

?的实用性很容易理解。如果你想同时找到 httphttps,你可以使用这样的模式:

https?

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

可选(惰性)量词

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

假设您有一组需要验证和解析的输入:

Input:
http123
https456
httpsomething


Expected result:
Pass/Fail  Group 1   Group 2
Pass       http      123
Pass       https     456
Pass       http      something

你可以试试脑海中浮现的第一件事,那就是 这个:

^(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

好吧,让我们看看 再试一次。假设第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

现在第二个输入很好,但是第三个输入分组错误,因为缺省情况下 ?是贪婪的(+也是,但是 ?先出现)。当决定 shttps?还是 [a-z]+|\d+的一部分时,如果结果是通过,的正则表达式引擎总是选择左边的那个。因此第二组失去了 s,因为第一组吸收了它。

为了解决这个问题,你需要制作 一个小小的改变:

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

本质上,这意味着: “匹配 ABC0如果你必须,但看看这是否仍然通过时,组1只是 http。”引擎意识到 s可以作为 [a-z]+|\d+的一部分工作,因此它倾向于将其放入第2组。

???的关键区别在于它们的 懒惰??是惰性的,而 ?不是。

假设您希望在一组文本中搜索单词“ car”,但是不希望仅限于单数“ car”; 还希望匹配复数“ car”。

这里有一个例句:

I own three cars.

现在,如果我想匹配单词“ car”我只想得到字符串“车”作为回报,我会像下面这样使用惰性 ??:

cars??

这意味着,“查找单词 car 或 car; 如果找到其中任何一个,返回 car,仅此而已”。

现在,如果我想匹配相同的单词(“ car”或“ car”) 我想要得到整场比赛的回报,我会像下面这样使用非惰性 ?:

cars?

上面写着,“查找单词 car 或者 car,然后返回 car 或者 car,不管你找到什么”。

在计算机编程的世界里,惰性通常意味着“只评估所需要的数量”。因此,惰性 ??只返回匹配所需的内容; 因为“ car”中的“ s”是可选的,所以不要返回它。另一方面,非惰性(有时称为 贪婪)操作尽可能多地求值,因此 ?返回所有匹配,包括可选的“ s”。

就我个人而言,我发现自己使用 ?作为一种使其他正则表达式操作符(如 *+操作符)懒惰的方法,比我使用它作为简单的字符可选性的方法更多,但 YMMV。

用密码看

以下是在 Clojure 实施的一个例子:

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


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

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

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

除了在其他答案中解释的内容之外,< strong > 在正则表达式中还有3种使用问号的方法。    

  1. 负面展望

    如果您愿意,可以使用负向前视 匹配某物而不是后面跟着其他东西。否定句 Lookahead 结构是一对括号,其中的开头部分为 括号后面加一个问号和一个叹号

    例子

    • 考虑一个单词 There
    • 现在,默认情况下,RegExe将找到单词 There中的第三个字母 e

      There
      ^
      
    • However if you don't want the e which is immediately followed by r, then you can use RegEx e(?!r). Now the result would be:

      There
      ^
      
  2. Positive Lookahead

    Positive lookahead works just the same. q(?=u) matches a q that is immediately followed by a u, without making the u part of the match. The positive lookahead construct is a pair of parentheses, with the opening parenthesis followed by a question mark and an equals sign.

    example

    • Consider a word getting
    • Now, by default, the RegEx t will find the third letter t in word getting.

      getting
      ^
      
    • However if you want the t which is immediately followed by i, then you can use RegEx t(?=i). Now the result would be:

      getting
      ^
      
  3. Non-Capturing Groups

    Whenever you place a Regular Expression in parenthesis(), they create a numbered capturing group. It stores the part of the string matched by the part of the regular expression inside the parentheses.

    If you do not need the group to capture its match, you can optimize this regular expression into

    (?:Value)
    

See also this and this.

从 Oracle 文档中运行测试工具包,使用“一次或根本不匹配”匹配 X??这个勉强的量词,可以看出它是一个保证始终为空的匹配。

$ 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.

Https://docs.oracle.com/javase/tutorial/essential/regex/quant.html

看起来和空火柴一模一样。

Enter your regex:
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.


Enter your regex:
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.


Enter your regex: x??
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.