为什么在 PHP 中三个反斜杠等于四个反斜杠?

5
<?php
$a='/\\\/';
$b='/\\\\/';
var_dump($a);//string '/\\/' (length=4)
var_dump($b);//string '/\\/' (length=4)
var_dump($a===$b);//boolean true
?>

为什么在PHP中,带有3个反斜杠的字符串等于带有4个反斜杠的字符串?

我们能在正则表达式中使用3个反斜杠的版本吗?

PHP参考文档中指出我们必须使用4个反斜杠。

注意: 单引号和双引号的PHP字符串具有反斜杠的特殊含义。因此,如果要将\与正则表达式匹配,则必须在PHP代码中使用"\\\\"'\\\\'


它也是基于分隔符的。 - Avinash Raj
2个回答

4
$b='/\\\\/';

PHP逐个字符解析字符串(或多或少)。第一个输入符号是正斜杠。结果是在结果中有一个正斜杠(解析步骤)和从输入中取走的输入符号(一个字符,即/)。
下一个输入符号是反斜杠。它从输入中取出并检查下一个字符/符号。这也是一个反斜杠。这是一个有效的组合,因此第二个符号也从输入中取出,结果是单个反斜杠(对于两个输入符号均适用)。
第三个和第四个反斜杠同理。
最后一个输入符号(在字面上)是正斜杠->结果中的正斜杠。
-> / \ /

现在看一下带有三个反斜杠的字符串:

$a='/\\\/';

PHP会“找到”第一个反斜杠,接下来的字符是一个反斜杠 - 这是一个有效组合,结果在输出中只有一个反斜杠,并且输入字面量中的两个字符都被取出。 然后PHP“找到”第三个反斜杠,接下来的字符是一个正斜杠,这不是一个有效组合。因此,结果只有一个反斜杠(因为PHP爱你并原谅你……),并且只有一个字符被取出。 下一个输入字符是正斜杠,在输出中得到一个正斜杠。
-> /\\/

=> 两个字面量编码了相同的字符串。


4
在关于字符串的页面中的文档中解释了这一点:
单引号部分中,它说:
最简单的指定字符串的方法是将其放在单引号(字符')中。
要指定文字单引号,请使用反斜杠进行转义(\)。要指定文字反斜杠,请将其加倍(\\)。所有其他反斜杠实例将被视为文字反斜杠。
让我们来尝试解释你的字符串:
$a='/\\\/';

斜杠 (/) 在 PHP 字符串中没有特殊的含义,它们代表它们自己。
第一个反斜杠 (\) 转义了第二个反斜杠,正如上面第二段引用中的第一句所解释的那样。
第三个反斜杠代表它本身,正如上述引用的最后一句所解释的那样,因为它后面没有跟随撇号 (') 或反斜杠 (\)。

因此,变量 $a 包含这个字符串:/\\/

结束。

$b='/\\\\/';

有两个反斜杠(第二个和第四个)被第一个和第三个反斜杠转义。最终(运行时)字符串与$a相同:/ \ /

注意

上面的讨论是关于PHP源代码中字符串的编码。正如您所看到的,总是有多种(正确的)方式来编码相同的字符串。除了使用单引号或双引号括起来的字符串文字、使用heredocnowdoc语法之外,其他选项(例如使用常量(用于文本反斜杠)并从片段构建字符串)也是可行的。

例如:

define('BS', '\');       // can also use '\\', the result is the same
$c = '/'.BS.BS.'/';

该代码不使用转义符号,只使用一个反斜杠。常量BS包含了一个反斜杠,并且在需要其本身值的情况下被广泛使用。在需要用反斜杠进行转义时,则使用真正的反斜杠(无法使用BS进行转义)。

regex中的转义是不同的。首先,在运行时解析regex时,无论它们是如何生成的,$a$b$c都包含/ \ /

然后,在regex中,如果反斜杠后面没有特殊字符,则会被忽略(请参见上文中的差异,在PHP中,它被解释为字面反斜杠)。

结合 PHP 和 regex

有无数的可能性使事情变得复杂。让我们尝试保持简单,并为PHP中的regex制定一些指南:

  • 如果可能的话,将regex字符串用撇号(')括起来,这样在PHP中只需要转义两个字符:撇号和反斜杠;
  • 解析URL、路径或其他可能包含正斜杠(/)的字符串时,使用#~!@作为regex分隔符(其中一个没有在regex本身中使用); 这样,在regex内部使用分隔符时就不需要转义它;
  • 当不需要时,不要在regex中转义字符; 例如,破折号(-)仅在字符类中使用时具有特殊含义; 在它们之外,转义它是无用的(即使在字符类中,如果将其放置在[...]封闭符号的第一个或最后一个字符位置,则可以不带引号使用它而不具有任何特殊含义);

所以,如果我理解正确的话,那么转义反斜杠的唯一原因是,如果你想在单引号旁边使用它?所以它只是为了避免将 \'Hi 解析为 'Hi?否则,反斜杠无论如何都会被解析为反斜杠,对吧? - Adam
根据文档所述,如果您需要在字符串中表示反斜杠,则必须对其进行转义。这是正确的方法。然而,解析器是宽容的,如果反斜杠与下一个字符一起不构成有效的转义序列,则不会报告错误。在这种情况下,它理解反斜杠未被用作转义,但需要表示自身。虽然以这种方式使用似乎是安全的,但我不建议这种用法(我知道我在答案中使用了它)。从C派生的其他语言不会按此方式工作,并报告错误或忽略反斜杠。 - axiac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接