【问题标题】:How to properly escape a backslash to match a literal backslash in single-quoted and double-quoted PHP regex patterns如何正确转义反斜杠以匹配单引号和双引号 PHP 正则表达式模式中的文字反斜杠
【发布时间】:2013-12-28 19:08:03
【问题描述】:

为了匹配文字反斜杠,很多人和the PHP manual 说:总是三重转义它,就像这样\\\\

注意

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

这是一个示例字符串:\test

$test = "\\test"; // outputs \test;

// WON'T WORK: pattern in double-quotes double-escaped backslash
#echo preg_replace("~\\\t~", '', $test); #output -> \test

// WORKS: pattern in double-quotes with triple-escaped backslash
#echo preg_replace("~\\\\t~", '', $test); #output -> est

// WORKS: pattern in single-quotes with double-escaped backslash
#echo preg_replace('~\\\t~', '', $test); #output -> est

// WORKS: pattern in double-quotes with double-escaped backslash inside a character class
#echo preg_replace("~[\\\]t~", '', $test); #output -> est

// WORKS: pattern in single-quotes with double-escaped backslash inside a character class
#echo preg_replace('~[\\\]t~', '', $test); #output -> est

结论

  • 如果模式是单引号,反斜杠必须双转义 \\\ 以匹配文字 \
  • 如果模式是双引号,则取决于是否 反冲在一个字符类中,它必须至少被双重转义\\\ 在字符类之外,它必须被三重转义 \\\\

谁能告诉我一个不同之处,其中单引号模式中的双转义反斜杠,例如'~\\\~' 将匹配与双引号模式中的三重转义反斜杠不同的任何内容,例如"~\\\\~" 或失败。

何时/为什么/在什么情况下在单引号模式中使用双转义 \ 是错误的,例如'~\\\~' 用于匹配文字反斜杠?

如果这个问题没有答案,我将继续在单引号 PHP 正则表达式模式中使用双转义反斜杠 \\\ 来匹配文字 \,因为它可能没有任何问题。

【问题讨论】:

  • \t 为 TAB 定义,当您将它放在双引号内时。因此,如果您使用任何其他示例,其中t 不会正好在反斜杠之后,这将是可观的。
  • 根据谷歌的说法,tripple 的意思是“一匹马的步态,左腿和右腿一起移动。”。我认为正确的拼写是triple。不知道您为什么要还原该编辑。
  • @Amal Murali 哎呀,对不起!文字中有很多tripples :-)接下来的15分钟我不会碰文字。
  • 有点不清楚你在问什么。能否请您改述一下这个问题?
  • @Jonny5 阅读此answer。主要的“想法”如下: PHP 使用正则表达式引擎,在本例中为 PCRE。当你写一个变量。它将通过 PHP,然后 PHP 会将其传递给正则表达式引擎。正则表达式引擎需要的是双反斜杠来匹配反斜杠。你如何做到这一点,在 PHP 中取决于你。我会一直使用 4 个反斜杠,这样既安全又能防止混淆。

标签: php regex preg-replace


【解决方案1】:

反斜杠字符 (\) 被 PHP 的解析器和正则表达式引擎 (PCRE) 视为转义字符。如果您编写单个反斜杠字符,它将被 PHP 解析器视为转义字符。如果你写了两个反斜杠,它将被 PHP 的解析器解释为文字反斜杠。但是当在正则表达式中使用时,正则表达式引擎会将其作为转义字符来选择。为避免这种情况,您需要编写四个反斜杠字符,具体取决于您引用模式的方式。

要了解这两种引用模式之间的区别,请考虑以下两个var_dump() 语句:

var_dump('~\\\~');
var_dump("~\\\\~");

输出:

string(4) "~\\~"
string(4) "~\\~"

转义序列\~ 在PHP 中用于单引号字符串时没有特殊含义。三个反斜杠也可以工作,因为 PHP 解析器不知道转义序列 \~。所以\\ 将变为\\~ 将保持为\~

你应该使用哪一个:

为了清楚起见,当我想匹配文字反斜杠时,我总是使用~\\\\~。另一个也可以,但我认为~\\\\~ 更清楚。

【讨论】:

  • @Jonny5: 很高兴能帮上忙 :)
  • 在阅读single-quote section in PHP manual 后,我更加了解单引号内的反斜杠只是单引号或反斜杠之前的转义字符。在任何其他情况下,它都被视为文字。 '\\\' 是不可能的,因为你会转义结束 ',但 '~\\\~' 将是一个转义的反斜杠,后跟一个文字反斜杠,因为它不是任何其他反斜杠或单引号之前的转义字符.
  • 我询问了一些示例,其中双转义的反斜杠将匹配与三重转义不同的内容。此模式无法工作,因为它会破坏字符串并导致解析错误:$pattern = '~[\\\\']~',而这与反斜杠不匹配:$pattern = '~[\\\']~';$pattern = '~[\'\\\]~';$pattern = "~[\\\\']~"; 在这种特殊情况下可以工作。
  • 在上面的示例中,我想使用character-class 匹配单引号或反斜杠。 $pattern = '~[\\\\']~'; 说明存在单引号模式中的三重转义反斜杠无法工作的情况。立即了解how to escape,让一切变得简单。
  • 当然,对我来说,它解决了问题并包含了解决方案,这是在理解 how escaping in PHP-strings 工作,正则表达式解析器得到正确转义的输入。
【解决方案2】:

PHP 中单引号或双引号字符串中的斜线的实际转义没有区别——只要你做对了。正如 cmets 中指出的那样,您在第一个示例中获得 WONT WORK 的原因是,它将 \t 扩展为制表符元字符。

当您只使用三个反斜杠时,单引号字符串中的最后一个将被解释为 \~,就单引号字符串而言,它将保持原样(因为它不匹配有效的转义序列)。然而,这只是一个巧合,在这种情况下,它将按照您的预期进行解析,并且不会产生某种副作用(即 \\\' 的行为方式不同)。

所有转义的原因是正则表达式在某些情况下也需要转义反斜杠,因为它们在那里也有特殊含义。这会导致大量的反斜杠一个接一个,例如 \\\\(对于降价解析器需要八个反斜杠,因为它再次增加了另一层转义)。

希望这可以清除它,因为您似乎对单/双引号字符串中的反斜杠的处理感到困惑,而不是正则表达式本身的行为(无论“或”,只要你正确地逃避事情)。

【讨论】:

  • 请注意:您可以将它们包装在反引号中以避免额外的转义。 :)
  • @fiskfisk 非常感谢您的回答。我从您的两个答案中得出了我的理解,并且从现在开始会这样做。只是想了解一下。
猜你喜欢
  • 2016-12-13
  • 2020-10-28
  • 1970-01-01
  • 2012-07-30
  • 2020-12-04
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
相关资源
最近更新 更多