在top-voted answer到this fantastic question,下面的正则表达式是在preg_replace
调用中使用(从答案的auto_version
功能):为什么\。平等。在preg_replace?
'{\\.([^./]+)$}'
这个正则表达式的最终目标是从给定的文件名中提取文件的扩展名。然而,我很困惑这个正则表达式的开始为什么起作用。即:
为什么\\.
在正则表达式中与\.
的匹配方式相同?
不应该前者匹配(a)一个字面反斜杠,后跟(b)任何字符,而第二个匹配一个文字周期? single quoted strings的规则规定\\
会生成文字反斜杠。
考虑一个简单的例子:
$regex1 = '{\.([^./]+)$}'; // Variant 1 (one backslash)
$regex2 = '{\\.([^./]+)$}'; // Variant 2 (two backslashes)
$subject1 = '/css/foobar.css'; // Regular path
$subject2 = '/css/foobar\\.css'; // Literal backslash before period
echo "<pre>\n";
echo "Subject 1: $subject1\n";
echo "Subject 2: $subject2\n\n";
echo "Regex 1: $regex1\n";
echo "Regex 2: $regex2\n\n";
// Test Variant 1
echo preg_replace($regex1, "-test.\$1", $subject1) . "\n";
echo preg_replace($regex1, "-test.\$1", $subject2) . "\n\n";
// Test Variant 2
echo preg_replace($regex2, "-test.\$1", $subject1) . "\n";
echo preg_replace($regex2, "-test.\$1", $subject2) . "\n\n";
echo "</pre>\n";
输出是:
Subject 1: /css/foobar.css
Subject 2: /css/foobar\.css
Regex 1: {\.([^./]+)$} <-- Output matches regex 2
Regex 2: {\.([^./]+)$} <-- Output matches regex 1
/css/foobar-test.css
/css/foobar\-test.css
/css/foobar-test.css
/css/foobar\-test.css
长话短说:为什么要\\.
产生的preg_replace
呼叫作为\.
相同匹配的结果吗?
所以如果最终目标是匹配文字反斜杠,我想你必须考虑到可能发生的多层次的转义?就像'{\\\。}',产生'\\。'? –
@JonahBishop:的确如此。再次,PHP字符串中的三个或四个反斜杠将最终匹配正则表达式中的文字反斜杠(除非有三个后跟一个单引号,但是您会得到该图片)。 – Jon
这里的间接级别非常有趣。我明白为什么这种事情的测试用例是个好主意。谢谢你的出色答案。 –