任何人都可以解释这个评论删除正则表达式如何工作?

时间:2013-11-18 10:37:11

标签: php regex json string comments

这是其中一种情况,当你得到一些工作,但惊讶于它的工作情况。我有点麻烦理解为什么下面的正则表达式,即从JSON字符串中删除注释而不触及字符串值中的注释,无论在何种情况下都无条件地适用于所有情况,无论我在评论中添加了多少双引号“傻瓜“正则表达式:

$str = <<<'ndoc'
{
    // comment "
    "prop0": /* remove */ "hello /* preserve */ there", // remove
    "prop1": /* remove " */ "hi // preserve", /* remove " */
    "prop2": /* remove */ "hi // preserve"
}
ndoc;
$str = preg_replace("/\"(?<!\\\\\")(?:[^\\\\\"]++|\\\\{2}|\\\\.)*\"(*SKIP)(*FAIL)|\\/\\/.*(?=\\R)|\\/\\*\\C*?\\*\\//u", "", $str);
var_dump($str);

http://ideone.com/rLP1nq

在我看来,必须跳过第一条评论中双引号和prop0中双引号的文本,然后必须跳过": /* remove */ ",依此类推,不是删除需要删除的注释并删除需要保留的文本。但正则表达式无论如何都可行。为什么呢?

1 个答案:

答案 0 :(得分:1)

我重新格式化了您的来源并为该模式添加了评论。分隔符更改为(),使得不需要转义斜杠。 x modifer允许格式化模式(忽略空格,#comments可能)。

这应该使模式更具可读性。您可以看到第一部分与“value”-String匹配。如果匹配,则跳过替换,否则匹配并替换//和/ ** / comments。

$str = <<<'ndoc'
{
    // comment "
    "prop0": /* remove */ "hello /* preserve */ there", // remove
    "prop1": /* remove " */ "hi // preserve", /* remove " */
    "prop2": /* remove */ "hi // preserve"
}
ndoc;

$pattern = "(
  # a starting double quote
  \" 
  # string contents including escape sequences
  (?<!\\\\\")(?:[^\\\\\"]++|\\\\{2}|\\\\.)* 
  # the ending double quote
  \"
  # skip double quote string matches
  (*SKIP)(*FAIL) 
  # or
  | 
  # // comments
  //.*(?=\\R)  
  # or
  | 
  # /* */ comments
  /\\*\\C*?\\*/
)xu";

$str = preg_replace($pattern, "", $str);
var_dump($str);