3

这个奇妙问题的最高投票答案中,调用中使用了以下正则表达式(来自答案的函数):preg_replaceauto_version

'{\\.([^./]+)$}'

这个正则表达式的最终目标是从给定的文件名中提取文件的扩展名。但是,我很困惑为什么这个正则表达式的开头有效。即:

为什么\\.匹配方式与\.正则表达式相同?

前者不应该匹配(a)一个文字反斜杠,然后是(b)任何字符,而第二个匹配一个文字句点吗?单引号字符串的规则规定产生\\文字反斜杠。

考虑这个简单的例子:

$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\.

4

2 回答 2

11

考虑一下双重转义:PHP 看到\\.并说“好的,这真的是\.”。然后正则表达式引擎看到\.并说“好的,这意味着一个文字点”。

如果删除第一个反斜杠,PHP 会看到\.并说“这是一个反斜杠,后跟一个随机字符——不是单引号或反斜杠,按照规范——所以它仍然存在\.”。正则表达式引擎再次看到\.并给出与上面相同的结果。

于 2013-01-23T16:09:26.713 回答
0

乔恩完美正确答案的补充:

请考虑使用不同类型的引号("vs ')。如果使用',则不能包含控制字符(如换行)。通过使用可以是不同事物"的特殊组合键(如、等),这是可能的。所以,如果你想在你的双引号字符串中有一个实数,你需要使用. 请注意,使用单引号时,这不是必需的。\??\n\t\\\

于 2013-01-23T16:18:49.387 回答