【问题标题】:What's the difference between * and ? in regular expressions?* 和 有什么区别?在正则表达式中?
【发布时间】:2011-05-08 05:04:23
【问题描述】:

两者似乎都意味着匹配 0 个或更多字符?我不明白它们之间的区别,或者什么时候使用?,什么时候使用*。一些例子会有所帮助。

【问题讨论】:

  • 如果您使用 * 和 ?在正则表达式的上下文中,* 将匹配紧接在 ? 之前的字符的最小 0 次和最大 1 次。并且 A * 将匹配紧接在 * 之前的字符的最小 0 次和最大任意次数。在全局/通配符的上下文中,? 将匹配该位置的一个字符,它可以是任何字符(不必是前面的)。 * 将匹配出现 * 的位置的任意数量的任意字符。

标签: regex


【解决方案1】:
  • 正式定义中,正则表达式运算符的符号为

    . :像 a.b.c 这样的连接将匹配具有 abc 的文本。有时为了表示连接,只需背靠背使用两个符号。

    *:匹配最后一个符号 0 次或多次,(abc)* 将匹配空字符串 abc、abcabc、abcabcabc,但不匹配 abcaabc。被称为克莱恩之星。

    + :将匹配左侧或右侧。 (abc + def) 将匹配 abc 或 def。还使用联合运算符或| 运算符。

    这些应用于一组符号sigma,其中包括您的语言中的符号,其他特殊符号是表示空字符串的epsilon,以及表示空字符串的null 表示根本没有符号。详情见[3]

    这些是正式的定义。

当您使用接受 POSIX 正则表达式语法的应用程序时,不同运算符的含义如下:

  • 这些是 POSIX 基本正则表达式操作

    . : 点 '.'匹配任何字符,如 a.c 可以匹配 abc、axc、amc、aoc 任何字符。

    ^ :表示行首。 ^abc 将匹配从该行开始的字符串。出现在行之间的 abc 将不匹配

    $ :表示行尾。 abc$ 只会匹配行尾的字符串 abc。这不会匹配行之间的任何“abc”。

    * :匹配 '*' 之前的最后一个符号 0 次或更多次。所以ab*c会匹配ac、abc、abbc、abbbc、abbbbbc、abbbbbbbbc等。

    {m, n} :至少匹配前面的符号“m”次,最多匹配“n”次。 ab{2,4}c匹配'abc',但会匹配'abbc'、'abbbc'、'abbbbc',但将匹配'abbbbbc'。因此,如果 'b' 的数量 >= 2 且

    {m,} : 表示匹配前一个符号最少'm'次,最大没有限制。 (注意逗号)

    {n} :意味着匹配前面的符号正好'n'次。所以ab{3}c 只会匹配 'abbbc'。

    [symbols] :将匹配方括号内的任何一个符号。像 a[xyz]c 将匹配 'axc' 、 'ayc' 和 'azc' 而没有其他字符串

    [^symbols] :将匹配任何在方括号内 not 的符号。像 a[xyz]c 将匹配任何字符串 'a.b' 和 '.'是任何符号除了 x, y, z.

  • 这些是POSIX 扩展正则表达式 运算符(需要grep -E

    ? :将匹配前面的符号 0 次或最多 1 次。所以ab?c 只会匹配 'ac' 和 'abc'。

    + :将匹配前面的符号至少 1 次,最多任意次(没有上限)。就像ab+c 会匹配 abc、abbbc、abbbbbc、abbbbbbbbc 等,但会匹配 'ac'

    | :将匹配“|”左侧的任一表达式或“|”右侧的右侧表达式。喜欢(ab+c)|(xy*z)

  • 还可以查看 POSIX 元字符 类,例如 [:alpha:] 代表所有字母。 [:punct:] 表示所有的标点符号等。

  • Wild Characters/Globs 如果您使用*? 作为通配符,则解释如下

    * :匹配该位置任意数量的任意字符。像*.c 表示所有以字符串'.c' 结尾的字符串(这里. 没有特殊解释)。使用ls *.cls *.doc 进行测试

    ? : 在这个位置只匹配任何字符一次。就像file??.txt 会匹配字符串'fileab.c'、'file00.c' 等,并且匹配任意两个字符。使用ls *.??? 进行测试,它将列出所有具有三个字符扩展名的文件。

我希望这能回答您的问题。或者您可能想通过一些关于正式定义和 POSIX 以及 Perl 风格的正则表达式的文本来获得清晰的想法。

参考资料: Wikipedia Page

grep manual Regular expression section

Theory of Computation by Michael Sipser

注意: 这个答案是重构的

【讨论】:

  • 所以,(abc)? 将匹配 abc, abcd, abce, abcf 等,但不匹配 abcdef
  • 如果?被用作全局/通配符,那么它只会匹配带有 abc 的 4 个字符的字符串和 abc 之后的任何一个字母。如果你使用 ?用 grep 扩展正则表达式呢?最多匹配前面的字符一次。所以 abc?d 会匹配 abd, abcd
  • . 不是连接,它是任何单个字符,+ 将前一个字符/表达式(如果使用大括号)计算一次或多次。
  • 是的,. 确实根据 POSIX 语法匹配任何字符 link 如果您查看正式定义,那么 . 表示连接,或者简单地写两个符号也背靠背表示串联。
  • 您对.+ 的解释是完全错误的。正确答案见@icktoofay 和@manojlds ==> -1。 http://www.regular-expressions.info/ 是一个学习正则表达式的好网站。
【解决方案2】:

? 表示零或之一。 * 表示任意数量。所以这个:

^ab?$

将匹配 aab,但不匹配 abb。这个:

^ab*$

不仅可以匹配aab,还可以匹配abbabbba 以及后面的任意数量的bs。

【讨论】:

  • 吹毛求疵:ab? 将匹配 abb 的字母 ab;它与第二个b 不匹配。如果正则表达式是^ab?$,那么它将不匹配abb。为了完整起见,您还可以提及ab+,它不会匹配a,但会匹配ababbabbb,等等(匹配一项或多项)。
  • 如果我输入[ab]? 会怎样,那会有效吗?
  • 它将不匹配任何内容,“a”或“b”。
  • @rmhh 那么你想在什么样的情况下使用?呢?好像没用。。
  • 当你想要一个可能只出现一次的可选部分时,如That's a nice colou?r。您不想使用 *,因为它会匹配 Thats a nice colouuuuuur
【解决方案3】:

为了正则表达式的完整性,还使用了 *? 之类的东西。在这种情况下,它是惰性匹配或非贪婪匹配,并且会在匹配下一个标记之前匹配尽可能少的字符。

例如:

a.*a

匹配整个 abaaba

同时

a.*?a

将匹配abaaba

【讨论】:

    猜你喜欢
    • 2016-03-12
    • 1970-01-01
    • 2020-08-10
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    • 2013-04-16
    • 2021-07-14
    相关资源
    最近更新 更多