通过正则表达式删除块注释

7

我在尝试使用这个正则表达式时遇到了困难。我只是想删除块注释。目前为止,我已经做到了这一点,但是我无法去掉最后的*/

$string = 'this is a test /*asdfa  */ ok then';

$pattern = '/\/\*([^\*\/]*)/i';

$replacement = '';

echo preg_replace($pattern, $replacement, $string);

//this is a test */ ok then

任何帮助都会受到欢迎。

2
PHP不是一种常规语言,因此无法使用正则表达式解析它或删除所有有效的块注释。 - Paul Tomblin
2
@Paul:你不能使用正则表达式解析PHP,但是你可以进行词法分析。你不需要完整的解析器来去除注释(事实上,通常在词法分析中就会丢弃注释,而不是在解析中进行)。 - Billy ONeal
1
@Billy 不可以。http://zh.wikipedia.org/wiki/乔姆斯基谱系 - Alin Purcaru
2
看这个例子:"this is a comment /* or is it? */"。字符串内的注释应该被删除吗?想让它变得更复杂吗?那就使用heredoc。 - Alin Purcaru
1
@Billy 为什么你认为语法高亮器使用正则表达式而不是标记?至于使用正则表达式删除注释,我会考虑它可能是可行的(但仅适用于注释或其他语言的有限子集)。如果可以的话,我想看一些这样做的例子。 - Alin Purcaru
显示剩余18条评论
7个回答

6
尝试把这个作为你的模式:
/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/

我不明白...那里的\r\n是做什么用的? - Billy ONeal
它可以去除换行符。虽然在他给出的示例中可能不需要,但这是我用来删除多行注释的方法。 - wajiw
@wajiw:为什么不让它匹配任何字符?我不知道换行符有什么特别之处。 - Billy ONeal
我遇到了一个问题,即 .* 无法匹配换行符。 - wajiw
@wajiw:啊..我忘了这个。使用m修饰符使.匹配换行符。 - Billy ONeal
1
是的,这是更聪明的做法 :-) 谢谢 - wajiw

6

使用与/不同的分隔符会让它变得混乱。

那么尝试使用'#/\*.+?\*/#s'如何?


1
不过,那里应该有一个“m”修饰符吗?(免责声明:我在多行正则表达式方面有点生疏。) - BoltClock
你实际上需要使用s(DOT_ALL),而不是m - Alin Purcaru
@Billy - 谢谢。这个我能理解,而且对于想要摆脱 /*** a */ 的情况实际上是有效的 - 其他一些答案在这种情况下不起作用。此外,我认为使用这个比使用分词器要简单得多。 - Abs
1
@Abs:1. 谢谢你,2. 公平地说,分词器会更准确。 (但是,你已经知道了;) ) - Billy ONeal

6
使用 token_get_all 函数对代码进行分词,并剔除 T_COMMENT 标签后重新构建代码。我认为不需要再多说什么了。

每个人都喜欢分词器。第二句话也加一分。 - BoltClock
过度解决方案是过度的。正则表达式足够并且更适合这个用例。(并不是说分词器内部不会使用它们) - mario
@Alin Purcaru:我没有对任何地方做出断言,而是明确说了“这个用例”。是的,我确实知道一些关于它们的事情,并且我也写过几个标记器。 - mario
@mario 在特定条件下使用一些正则表达式来查找标记,与使用 一个 正则表达式是不同的。 - Alin Purcaru
正则表达式并不是邪恶的,而是具有欺骗性的。如果你想使用它们来查找代码中的模式,那么在这样做之前,你应该至少考虑三次。构建一个只能找到注释的正则表达式,就像问题提问者所希望的那样,如果不是不可能的话,也非常困难。 - Alin Purcaru
显示剩余3条评论

1
我正在使用这个(请注意,您只需要第一行来处理/*...*/注释):
  #-- extract /* ... */ comment block
  #  or lines of #... #... and //... //...
  if (preg_match("_^\s*/\*+(.+?)\*+/_s", $src, $uu)
  or (preg_match("_^\s*((^\s*(#+|//+)\s*.+?$\n)+)_ms", $src, $uu))) {
     $src = $uu[1];
  }
  // Public Domain, not CC

运作得相当不错。但像所有正则表达式解决方案一样,它将在$PHP ="st/*rings"的边缘情况下失败。


不要说“像所有正则表达式解决方案一样”,因为你是错的。只能说这里提供的解决方案对于这个任务来说太过原始。 - tchrist
1
@tchrist:我的错。在试图纠正正则表达式的诽谤时,我自己也过于概括了。 - mario

0

可能是:

$pattern = '/\/\*([.]*)\*\//i';

请不要进行负面评价,因为这只是一个快速猜测,旨在提供帮助... :)

0
运行两次带有模式/\*|\*/preg_replace应该能够工作。

2
这只是去掉了注释分隔符,而不是注释文本本身。 - Billy ONeal

0

仅针对您的主要模式进行修复,我可以告诉您,您没有匹配最后的 "*/",因为您在模式中缺少它。

按照您自己的模式,尝试进行以下小修改:

'/\/\*([^\*\/]*)**\*\/**/i'

我还建议您使用不同的分隔符使模式更易于阅读。

#/\*([^\*/]*)\*/#i


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接