【问题标题】:Regex failing when pattern involves dollar sign ($)当模式涉及美元符号 ($) 时,正则表达式失败
【发布时间】:2011-07-18 11:57:39
【问题描述】:

在匹配涉及美元符号的子模式时,我遇到了一些问题。例如,考虑以下文本块:

Regular Price: $20.50       Final Price: $15.20
Regular Price: $18.99       Final Price: $2.25
Regular Price: $11.22       Final Price: $33.44
Regular Price: $55.66       Final Price: $77.88

我试图用以下正则表达式匹配常规/最终价格集,但它根本不起作用(根本没有匹配):
preg_match_all("/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U", $data, $matches);

我逃脱了美元符号,所以给出了什么?

【问题讨论】:

  • 尝试在美元符号上使用 \\\ 进行转义。可以推断问题美元符号与 PHP 使用 $ 执行某些工作的事实之间的关系。 (我也用 $ 做工作,这似乎是合乎逻辑的)。
  • 你试过不转义$的单引号吗?

标签: php regex


【解决方案1】:

在双引号字符串中,反斜杠被视为$ 的转义字符。 PHP 解析器甚至在 preg_match_all 函数看到它之前就删除了反斜杠:

$r = "/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U";
var_dump($r);

输出(ideone):

"/正常价格:$(\d+\.\d{2}).*最终价格:$(\d+\.\d{2})/U" ^ ^ 反斜杠不再存在

要解决此问题,请使用单引号字符串而不是双引号字符串:

preg_match_all('/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U',
               $data,
               $matches);

在线查看:ideone

【讨论】:

  • ... 或者您也可以在 \$ 之前添加一个 \ 以获得相同的结果。它不那么漂亮,但效果一样好。
  • 我遇到了同样的问题,现在感觉很愚蠢,谢谢!
【解决方案2】:

我知道这个问题有点老了,但我在尝试找到相同问题的答案时发现了这个问题。我看到它在搜索引擎排名中名列前茅,所以我想最好解释一个简单的替代方案,以及为什么会出现这种情况与双引号字符串 ( " )

我使用的正则表达式包含大量单引号字符 ( ' ),因此我不太热衷于用它们包装表达式,因为我不想转义所有这些字符。

我的解决方案是“双重转义”美元符号。在您的示例中,它应该类似于

"/Regular Price: \\\$(\d+\.\d{2}).*Final Price: \\\$(\d+\.\d{2})/U";

请注意,美元符号现在包含 3 个斜线 \\\

基本上,我们有两个“级别”的解释,即 PHP 的解释和正则表达式的解释。发生的情况是,使用一个斜杠,PHP 将其解释为文字字符而不是变量修饰符,因此它会吃掉斜杠,按照 Mark 的答案中概述的方式解释字符串,然后将其发送到正则表达式,后者解释为后视。

通过“双重转义”美元符号,PHP 将 \\\$ 分别解释为 \\\$。我们从第一组字符中转义\,并从第二组字符中转义$,在PHP 解释后得到\$。这将发送文字字符串

"/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U";

到正则表达式,它将\$ 解释为字符文字$,它将匹配$,而不是充当后面的样子,因为它被转义了。在这里实现双层解释很重要,因为 PHP 和 regex 都有自己的解释规则,最多可能需要 4 个斜杠才能正确转义字符。

单引号字符串没有这个问题,因为要在字符串中使用变量$foo,我们必须写

'Hello '. $foo .'!';

而不是

"Hello $foo!";

就像我们可以在双字符串中一样。与双引号字符串不同,单引号字符串不能将字符串内的变量解释为变量(除非它们像上面的示例一样附加),而是将它们解释为纯文本。由于我们不再需要对变量进行转义,因此我们只需

'/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U'

这会将\$ 发送到正则表达式,与双引号字符串中的\\\$ 相同。

这完全取决于您使用哪种样式或哪种样式更容易的个人喜好问题。

TL;DR:将\$ 用于'/Hello \$bob/is' 等单引号字符串,将\\\$ 用于"/Hello \\\$bob/is" 等双引号字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 2022-12-04
    • 2020-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多