在匹配涉及美元符号的子模式时,我遇到了一些问题.例如,考虑以下文本块:
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
Run Code Online (Sandbox Code Playgroud)
我试图将常规/最终价格集与以下正则表达式匹配,但它根本不起作用(根本没有匹配):
preg_match_all("/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U", $data, $matches);
我逃过了美元符号,所以给出了什么?
Mar*_*ers 39
在双引号字符串中,反斜杠被视为转义字符$.即使在preg_match_all函数看到之前,PHP解析器也会删除反斜杠:
$r = "/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U";
var_dump($r);
Run Code Online (Sandbox Code Playgroud)
输出(ideone):
"/Regular Price: $(\d+\.\d{2}).*Final Price: $(\d+\.\d{2})/U"
^ ^
the backslashes are no longer there
要解决此问题,请使用单引号字符串而不是双引号字符串:
preg_match_all('/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U',
$data,
$matches);
Run Code Online (Sandbox Code Playgroud)
看到它在线工作:ideone
我知道这个问题有点老了,但我在试图找到同样问题的答案时发现了这个问题.我看到它在搜索引擎排名的顶部,所以我认为解释一个简单的替代方案会很好,为什么这会发生在双引号字符串中( " )
我使用的正则表达式中包含大量单引号字符( ' ),所以我不太热衷于用它们包装表达式,因为我不想逃避所有这些.
我的解决方案是"双重逃脱"美元符号.在您的示例中,它应该看起来类似于
"/Regular Price: \\\$(\d+\.\d{2}).*Final Price: \\\$(\d+\.\d{2})/U";
Run Code Online (Sandbox Code Playgroud)
请注意,美元符号现在包含3个斜杠\\\.
基本上,我们有两个"级别"的解释,PHP和正则表达式.发生的事情是,使用一个斜杠,PHP将其解释为文字字符而不是变量修饰符,因此它吃掉斜杠,按Mark的答案中所述解释字符串,然后将其发送到regex,后者将其解释为后视.
通过"双重逃避"美元符号,PHP 分别解释\\\$为\\和\$.我们\从第一组字符中逃脱,并$从第二组中逃脱,导致在\$PHP解释之后.这将发送文字字符串
"/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U";
Run Code Online (Sandbox Code Playgroud)
regex,它将被解释\$为字符文字$,它将匹配$而不是作为后面的外观,因为它被转义.在这里实现双层解释很重要,因为PHP和正则表达式都有自己的解释规则,并且最多可能需要4个斜杠来正确转义字符.
单引号字符串没有这个问题,因为要$foo在字符串中使用变量,我们必须写
'Hello '. $foo .'!';
Run Code Online (Sandbox Code Playgroud)
代替
"Hello $foo!";
Run Code Online (Sandbox Code Playgroud)
就像我们可以在双弦.与双引号字符串不同,单引号字符串不能将字符串中的变量解释为变量(除非它们像上面的示例中那样被附加),而是将它们解释为纯文本.因为我们不再需要逃避变量,所以我们可以逃脱
'/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U'
Run Code Online (Sandbox Code Playgroud)
它将发送\$到正则表达式,与\\\$双引号字符串相同.
这完全取决于您使用哪种风格的个人偏好,或者哪种模式更容易.
TL; DR:\$用于单引号字符串,例如'/Hello \$bob/is',\\\$用于双引号字符串"/Hello \\\$bob/is".