【问题标题】:Convert Single Line Comments To Block Comments将单行注释转换为块注释
【发布时间】:2010-12-03 05:19:56
【问题描述】:

我需要将单行 cmets (//...) 转换为块 cmets (/*...*/)。我在下面的代码中几乎完成了这一点;但是,我需要跳过任何单行注释的功能已经在块注释中。目前它匹配任何单行注释,即使单行注释在块注释中。

 ## Convert Single Line Comment to Block Comments
 function singleLineComments( &$output ) {
  $output = preg_replace_callback('#//(.*)#m',
   create_function(
     '$match',
     'return "/* " . trim(mb_substr($match[1], 0)) . " */";'
   ), $output
  );
 }

【问题讨论】:

    标签: php regex comments


    【解决方案1】:

    如前所述,“//...”可以出现在块 cmets 和字符串文字中。因此,如果您使用正则表达式技巧创建一个小型“解析器”,您可以首先匹配其中任何一个(字符串文字或块-cmets),然后测试“//...”是否存在。

    这是一个小演示:

    $code ='A
    B
    // okay!
    /*
    C
    D
    // ignore me E F G
    H
    */
    I
    // yes!
    K
    L = "foo // bar // string";
    done // one more!';
    
    $regex = '@
      ("(?:\\.|[^\r\n\\"])*+")  # group 1: matches double quoted string literals
      |
      (/\*[\s\S]*?\*/)          # group 2: matches multi-line comment blocks
      |
      (//[^\r\n]*+)             # group 3: matches single line comments
    @x';
    
    preg_match_all($regex, $code, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
    
    foreach($matches as $m) {
      if(isset($m[3])) {
        echo "replace the string '{$m[3][0]}' starting at offset: {$m[3][1]}\n";
      }
    }
    

    产生以下输出:

    replace the string '// okay!' starting at offset: 6
    replace the string '// yes!' starting at offset: 56
    replace the string '// one more!' starting at offset: 102
    

    当然,PHP 中可能有更多的字符串文字,但我想你明白我的意思。

    HTH。

    【讨论】:

      【解决方案2】:

      你可以试试看消极的一面:http://www.regular-expressions.info/lookaround.html

      ## Convert Single Line Comment to Block Comments
      function sinlgeLineComments( &$output ) {
        $output = preg_replace_callback('#^((?:(?!/\*).)*?)//(.*)#m',
        create_function(
          '$match',
          'return "/* " . trim(mb_substr($match[1], 0)) . " */";'
        ), $output
       );
      }
      

      但是我担心其中可能带有 // 的字符串。喜欢: $x = "一些字符串 // 带有斜线"; 会被转化。

      如果你的源文件是 PHP,你可以使用 tokenizer 来更精确地解析文件。

      http://php.net/manual/en/tokenizer.examples.php

      编辑: 忘记了固定长度,您可以通过嵌套表达式来克服它。以上应该现在可以工作了。我测试了它:

      $foo = "// this is foo";
      sinlgeLineComments($foo);
      echo $foo . "\n";
      
      $foo2 = "/* something // this is foo2 */";
      sinlgeLineComments($foo2);
      echo $foo2 . "\n";
      
      $foo3 = "the quick brown fox";
      sinlgeLineComments($foo3);
      echo $foo3. "\n";;
      

      【讨论】:

      • 好吧,如果 $x = "some string // with slashes"; 我并不担心变成 $x = "some string /* with slashes */";.这实际上是首选。另一方面,我添加了您建议的更改并得到了编译错误。警告:preg_replace_callback() [function.preg-replace-callback]:编译失败:lookbehind assertion is not fixed length at offset 6 in C:\wamp\www\LessCSS\Site\cleaner\inc\util.php on line 29
      • PHP 的look-behind 只支持固定长度的断言。这意味着您不能编写与未定义数量的字符匹配的后视正则表达式,从而排除了 * 和 ? 的使用。更多信息在这里:php.net/manual/en/regexp.reference.assertions.php
      • 不适用于此:/* foo\n// shouldn't match\nbar */ - 您不希望它与第二行匹配,但它确实如此。
      • @Lance Rushing:我已经设法让代码工作预期具有新行字符的字符串,如 Alan Moore 所述。这是任何更新的功能,似乎您没有更新处理器。 ## 将单行注释转换为块注释 function sinlgeLineComments( &amp;$output ) { $output = preg_replace_callback('#^((?:(?!/*).)*?)//(.*)# m', create_function( '$match', 'return "$match[1] /* " . trim(mb_substr($match[2], 0)) . " <i>/";' ), $output ); }</i> 不应该匹配 $output = "/ foo\n// 不应该匹配\nbar */\nfoo more//应该匹配"
      猜你喜欢
      • 1970-01-01
      • 2019-02-21
      • 2017-08-07
      • 2014-09-29
      • 1970-01-01
      • 2014-01-15
      • 2022-01-28
      • 1970-01-01
      • 2011-10-27
      相关资源
      最近更新 更多