有人能解释一下这个删除正则表达式的注释是如何工作的吗


Can anyone explain how this comment-removing regex works?

这是一种情况,当你有一些东西要工作,但却对它的工作效果感到惊讶。我有点难以理解为什么下面的正则表达式,即从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 */ "必须跳过,以此类推,而不是删除需要删除的注释和删除需要保留的文本。但是regex无论如何都能正常工作。为什么?

我重新格式化了您的源代码,并向模式添加了注释。分隔符已更改为(),因此不需要对斜杠进行转义。x修改器允许格式化模式(忽略空白,可以使用#注释)。

这将使模式更易于阅读。您可以看到第一部分与"value"-字符串匹配。如果匹配,则跳过替换,否则匹配并替换//和/**/注释。

$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);