在PHP中使用POSIX正则表达式从C源代码中删除注释

时间:2015-03-07 18:17:36

标签: php regex

我在使用php和regex从C源代码中删除单行注释时遇到问题。

/* */条评论已删除,因此剩下的就是//条评论。

首先

我有这个正则表达式:$content = ereg_replace('^\/\/.*$', '', $content);

这将删除整个文件(不仅包含^//comment$的所有行)。我假设因为它贪婪的搜索,但我怎么能让它变得非贪婪?我怎样才能让它为所有符合条件的线做到?

第二次

问题是在字符串"//shall not be removed"中不应删除它们。我怎样才能做到这一点?当我发现"字符时,我在思考它应该跳过它,但我不知道该怎么做。

感谢所有帮助的人,我真的很喜欢它。

2 个答案:

答案 0 :(得分:1)

这将匹配所有单行注释,但是用双引号"包含的注释。甚至那些他们在评论中说的话!

(?=([^"\\]*(\\.|"([^"\\]*\\.)*[^"\\]*"))*[^"]*$)//.*$

<强> Live demo

* this answer

保留所有权利

答案 1 :(得分:1)

为避免字符串陷阱,一种方法是首先匹配您想要避免的内容并捕获它或跳过它。

自PHP 5.3起,

ereg_函数已被弃用,但始终可以使用它们:

$result = ereg_replace('("([^\\\"]|\\\.)*")|//[^' . "\n" . ']*|/\*\**([^*]|\*\**[^*/])*\*\**/', '\1', $str);

它有效,但如果你与preg版本(它有很多功能来改善模式)进行比较,表现非常糟糕

$pattern2 = '~
    " [^"\\\]* (?s: \\\. [^"\\\]* )*+ " # double quoted string
    (*SKIP)(*F) # forces the pattern to fail and skips the previous substring
  |
    /
    (?:
        / .* # singleline comment 
      |
        \*   # multiline comment 
        [^*]* (?: \*+(?!/) [^*]* )*+  
        (?: \*/ )? # optional to deal with unclosed comments
    )
~xS';

$result = preg_replace($pattern2, '', $str);

online demo

preg版本比ereg_版本快450倍。

子模式的详细信息 [^*]* (?: \*+(?!/) [^*]* )*+

此子模式描述了多行注释的内容,因此所有注释都在/*和第一个*/之间:

[^*]*           # all that is not an asterisk (can be empty)

(?:             # open a non capturing group:
                # The reason of this group is to handle asterisks that
                # are not a part of the closing sequence */

    \*+         # one or more asterisks 
    (?!/)       # negative lookahead : not followed by / 
                # (it is a zero-width assertion, in other words it's only a test 
                # and it doesn't consume characters)

    [^*]*       # zero or more characters that are not an asterisk
)*+             # repeat the group zero or more times (possessive)

字符串/*aaaa**bbb***cc***/的正则表达式引擎走(大约):

  

/* aaaa**bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 成功
  /* aaaa **bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 成功
  /*aaaa**bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 尝试群组
  /*aaaa ** bbb***cc***/ /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 成功
  /*aaaa** b bb***cc***/ /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 已验证
  /*aaaa** bbb ***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 成功
  /*aaaa**bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 尝试群组
  /*aaaa**bbb *** cc***/ /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 成功
  /*aaaa**bbb*** c c***/ /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 已验证
  /*aaaa**bbb*** cc ***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 成功
  /*aaaa**bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 尝试群组
  /*aaaa**bbb***cc *** / /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 成功
  /*aaaa**bbb***cc*** / /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 失败   /*aaaa**bbb***cc ** */ /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 回溯
  /*aaaa**bbb***cc** * / /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 验证
  /*aaaa**bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 成功
  /*aaaa**bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 尝试群组
  /*aaaa**bbb***cc** * / /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 成功
  /*aaaa**bbb***cc*** / /\* [^*]* (?: \*+ (?!/) [^*]* )*+ \*/ 失败   /*aaaa**bbb***cc***/ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 失败
  /*aaaa**bbb*** cc** */ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 回溯
  /*aaaa**bbb***cc** */ /\* [^*]* (?: \*+(?!/) [^*]* )*+ \*/ 成功