【问题标题】:Are ^$ and $^ in PHP regex the same?PHP 正则表达式中的 ^$ 和 $^ 是否相同?
【发布时间】:2011-09-17 10:01:49
【问题描述】:

为什么这两个正则表达式都匹配成功?

if(preg_match_all('/$^/m',"",$array))
  echo "Match";

if(preg_match_all('/$^\n$/m',"\n",$array))
  echo "Match";

【问题讨论】:

    标签: php regex preg-match anchor pcre


    【解决方案1】:

    $^ 是零宽度元字符。与其他元字符(如 . 一次匹配一个字符(除非与量词一起使用))不同,它们实际上并不匹配文字字符。这就是^$ 匹配空字符串"" 的原因,即使正则表达式(无分隔符)包含两个字符而空字符串包含零。

    空字符串不包含字符并不重要。它仍然有一个起点和一个终点,因为它是一个空字符串,所以两者都在同一个位置。因此,无论您使用^$ 的顺序或数量,它们的所有排列都应与空字符串匹配。


    您的第二种情况稍微复杂一些,但原理相同。

    m 修饰符 (PCRE_MULTILINE) 只是告诉 PCRE 引擎一次性输入整个字符串,而不考虑换行符,但字符串仍然包含“多行”。然后它将^$ 分别视为“行首”和“行尾”。

    字符串"\n"在逻辑上基本上分为三部分:"""\n"""(因为换行符被空虚包围……听起来很诗意)。

    然后这些匹配如下:

    1. 第一个空字符串与起始 $^ 匹配(正如我在上面解释的那样)。

    2. \n 与您的正则表达式中的相同 \n 匹配。

    3. 第二个空字符串与最后一个$匹配。

    这就是您的第二种情况导致匹配的方式。

    【讨论】:

    • 另外有趣的是,我发现这个场景类似于为什么空字符串是其自身的子字符串的问题。所以这根本不是一个愚蠢的问题。事实上,我刚刚投了赞成票!
    【解决方案2】:

    不,不是。实际上,表达式$^ 永远不应该匹配,因为$ 表示字符串的结尾,而^ 表示开头。但正如我们所知,结尾不能出现在字符串开头之前:)

    ^$ 应该匹配一个空字符串,仅此而已。

    “行首”元字符 (^) 仅匹配字符串的开头,而“行尾”元字符 ($) 仅匹配字符串末尾,[...]

    来自PCRE manpages

    请注意,通过添加 PCRE_MULTILINE 修饰符,$ 变为 EOL,^ 变为 BOL,它将匹配(感谢 netcoder 指出这一点)。不过,我个人不会使用它。

    【讨论】:

    • 那么为什么 '/$^\n$/m','\n' 匹配
    • 可能是因为它是您最喜欢的正则表达式引擎中的一个错误:) 或者它可能是这样定义的。但它在逻辑上没有意义,你永远不应该使用它。
    • @nEAnnam:这对我来说什么都不匹配,也不应该。
    • @x3ro:那么这是一个 PCRE 错误?因为我验证了问题代码并且$^ does 匹配空字符串(但不是上面的评论)。
    • 也许,因为两者都表示位置,它们在相同的位置匹配,因为我试过 $(space)^ 并且不起作用
    【解决方案3】:

    Regex.IsMatch ("", "$^") 在 C# 中也匹配。由于它是一个空字符串,因此没有大小。在索引 -1 处,它同时位于字符串的结尾和开头。好问题!

    【讨论】:

    • 有一个尺寸......它是0。(对不起,我无法抗拒;)
    • @BoltClock。 :-) 我应该说,there is no spoon。这个例子像黑客帝国一样让我心碎!
    【解决方案4】:

    在正则表达式中,^ 匹配字符串的开头,$ 匹配字符串的结尾。

    因此,正则表达式/^$/ 将成功匹配一个完全空的字符串(仅此而已)。

    /$^/ 不会匹配任何内容,因为从逻辑上讲,字符串的结尾不能在开头之前。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-13
      • 1970-01-01
      • 2011-04-02
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多