要在PHP PCRE函数中双重转义还是不双重转义?

Sub*_*ick 4 php regex

我正在寻找一篇关于什么时候需要双重逃逸以及什么时候没有,但我无法找到任何东西的文章.也许我看起来不够努力,因为我确定某处有一个解释,但让我们很容易找到有这个问题的下一个人!

以下面的正则表达式模式为例:

/\n/
/domain\.com/
/myfeet \$ your feet/
Run Code Online (Sandbox Code Playgroud)

没有什么可以突破的吗?好的,让我们在PHP的preg_match函数的上下文中使用这些示例:

$foo = preg_match("/\n/", $bar);
$foo = preg_match("/domain\.com/", $bar);
$foo = preg_match("/myfeet \$ your feet/", $bar);
Run Code Online (Sandbox Code Playgroud)

根据我的理解,带引号的字符串值的上下文中的反斜杠会转义后续字符,并且表达式是通过带引号的字符串值给出的.

以前会不会像下面这样做,这不会导致错误吗?:

$foo = preg_match("/n/", $bar);
$foo = preg_match("/domain.com/", $bar);
$foo = preg_match("/myfeet $ your feet/", $bar);
Run Code Online (Sandbox Code Playgroud)

这不是我想要的吗?那些表达方式与上面的不一样.

难道我不必像这样写双逃生吗?

$foo = preg_match("/\\n/", $bar);
$foo = preg_match("/domain\\.com/", $bar);
$foo = preg_match("/myfeet \\$ your feet/", $bar);
Run Code Online (Sandbox Code Playgroud)

因此,当PHP处理字符串时,它会将反斜杠转义为反斜杠,然后在传递给PCRE解释器时将其保留?

或者PHP只是神奇地知道我想将反斜杠传递给PCRE解释器...我的意思是它是如何知道我不是想\"逃避我想在我的表达中使用的引用?或使用转义报价时只需要双斜线?就此而言,你需要TRIPLE逃避报价吗?\\\"你知道吗,所以报价被转义并留下了双倍?

这个经验法则是什么?

我刚刚用PHP做了一个测试:

$bar = "asdfasdf a\"ONE\"sfda dsf adsf me & mine adsf asdf asfd ";

echo preg_match("/me \$ mine/", $bar);
echo "<br /><br />";
echo preg_match("/me \\$ mine/", $bar);
echo "<br /><br />";
echo preg_match("/a\"ONE\"/", $bar);
echo "<br /><br />";
echo preg_match("/a\\\"ONE\\\"/", $bar);
echo "<br /><br />";
Run Code Online (Sandbox Code Playgroud)

输出:

0

1

1

1
Run Code Online (Sandbox Code Playgroud)

因此,它看起来不知何故它对引号并不重要,但对于美元符号,我认为需要双重逃脱.

Ja͢*_*͢ck 8

双引号字符串

当涉及到双引号中的转义时,规则是PHP将在反斜杠之后立即检查字符.

如果相邻字符在集合中ntrvef\$"或者数字值跟随它(规则可以在这里找到),它将分别被评估为相应的控制字符或序数(十六进制或八进制)表示.

重要的是要注意,如果给出了无效的转义序列,则不计算表达式,并且反斜杠和字符都保留.这与其他语言不同,其中无效的转义序列会导致错误.

例如"domain\.com"将保持原样.

请注意,变量也会在双引号内扩展,例如"$var"需要转义为"\$var".

单引号字符串

从PHP 5.1.1开始,单引号字符串中的任何反斜杠(后跟至少一个字符)将按原样打印,也不会替换任何变量.这是迄今为止单引号字符串最方便的特性.

常用表达

对于转义正则表达式,最好将转义转义为preg_quote():

$foo = preg_match('/' . preg_quote('mine & yours', '/') . '/', $bar);
Run Code Online (Sandbox Code Playgroud)

这样您就不必担心需要转义哪些字符,因此它适用于用户输入.

也可以看看: preg_quote

更新

你添加了这个测试:

"/me \$ mine/"
Run Code Online (Sandbox Code Playgroud)

这被评估为"/me $ mine/"; 但在PCRE中它$具有特殊含义(它是一个主题终结锚).

"/me \\$ mine/"
Run Code Online (Sandbox Code Playgroud)

这被评估为"/me \$ mine/",因此反斜杠为PHP本身进行了$转义,而对于PCRE进行了转义.这只能偶然发挥作用.

$var = 'something';

"/me \\$var mine/"
Run Code Online (Sandbox Code Playgroud)

这被评估为"/me \something",所以你需要$再次逃避.

"/me \\\$var mine/"
Run Code Online (Sandbox Code Playgroud)