为什么 php 中的 3 个反斜杠等于 4 个反斜杠?

why 3 backslash equal 4 backslash in php?

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

为什么3个反斜杠的字符串和PHP中4个反斜杠的字符串相等?

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

PHP reference 说我们必须使用 4 个反斜杠。

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

$b='/\\/';

php 逐字符解析字符串文字(或多或少)。第一个输入符号是正斜杠。结果是(解析步骤的)结果中的正斜杠和输入符号(一个字符,/)从输入中取出。
下一个输入符号是反斜杠。它取自输入并检查下一个 character/symbol。这也是一个反斜杠。这是一个有效的组合,因此第二个符号也取自输入,结果是单个黑斜杠(对于两个输入符号)。
第三个和第四个反斜杠相同。
最后一个输入符号(在文字中)是结果中的正斜杠 -> 正斜杠。
-> /\/

现在对于带有三个反斜杠的字符串:

$a='/\\/';

php "finds" 第一个黑斜杠,下一个字符是黑斜杠 - 这是一个有效的组合,导致结果中有一个黑斜杠,输入文字中的两个字符都被采用。 php 然后 "finds" 第三个黑斜杠,下一个字符是正斜杠,这不是有效的组合。所以结果是一个单一的黑斜杠(因为 php 爱你并原谅你....)并且只从输入中取出一个字符。 下一个输入字符是正斜杠,导致结果中出现正斜杠。
-> /\/

=> 两个文字编码相同的字符串。

关于Strings页面的文档中有说明:

Single quoted 部分下它说:

The simplest way to specify a string is to enclose it in single quotes (the character ').

To specify a literal single quote, escape it with a backslash (\). To specify a literal backslash, double it (\). All other instances of backslash will be treated as a literal backslash.

让我们尝试解释您的字符串:

$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 和正则表达式

让事情变得复杂的可能性无穷无尽。让我们尽量保持简单,并在 PHP:

中为 regex 提供一些指导方针
  • 如果可能,将 regex 字符串括在撇号 (') 中;这样 PHP 只有两个字符需要转义:撇号和反斜杠;
  • 当解析 URL、路径或其他可以包含正斜杠 (/) 的字符串时,使用 #~!@ 作为regex 定界符(regex 本身没有使用);这样,当在 regex;
  • 中使用分隔符时,无需转义分隔符
  • 不要在不需要时转义 regex 个字符; f.e.,破折号(-)只有用在character classes中才有特殊意义;在它们之外,将它转义是没有用的(即使在字符 类 中,如果它被放置在 [...] 外壳内的第一个或最后一个字符,它也可以不加引号使用而没有任何特殊含义);