4

我来啦:

我正在编写一个 PHP 应用程序,并且我有一个新的官方域,现在所有常见问题解答都位于该域中。我脚本中的一些文件包含指向旧常见问题解答域的帮助链接,因此我想使用新域替换它们。但是,我只想保留链接到旧域的 URL,前提是它们位于评论或评论块下(我仍然使用旧域进行自我参考和其他文档)。

所以,基本上,我想要实现的是一个正则表达式,它可以在以下条件下工作:

  1. 匹配所有行中出现的example.com所有 *。
  2. 不要匹配整行,只匹配example.com字符串。
    • 如果该行以///*或“ *”开头,则与该单行中的任何实例都不匹配example.com(尽管,如果注释块在打开它的同一行中关闭,这可能是一个问题)。

我通常这样写我的块评论:

/* text
 * blah 
 * blah
*/

这就是为什么我不想匹配位于 、 或“ *”之后的“example.com ///*

我想它会是这样的:

^(?:(?!//|/\*|\s\*).?).*example\.com

但这有一个问题:它匹配整行,而不仅仅是“example.com”(这主要是当两个或多个“example.com”字符串在一行中匹配时会导致问题)。

有人可以帮我修复我的正则表达式吗?请注意:它不必是 PHP 正则表达式,因为我总是可以使用像 grepWin 这样的工具来一次在本地编辑所有文件。

哦,如果有办法以某种方式概括块评论,请告诉我,比如:一旦找到,在找到之前/*不匹配。那将非常有用。example.com*/是否可以在一般(非语言相关)正则表达式中实现它?

4

2 回答 2

2

我会使用某种标记器来区分评论和其他语言标记。

在处理 PHP 文件时,您应该使用PHP 自己的标记器函数token_get_all

$tokens = token_get_all($source);

然后您可以枚举标记并按类型分隔标记

foreach ($tokens as &$token) {
    if (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT, T_ML_COMMENT))) {
        // comment
    } else {
        // not a comment
        $token[1] = str_replace('example.com', 'example.net', $token[1]);
    }
}

最后,将所有内容与implode.

对于您手头没有合适的分词器的其他语言,您可以编写自己的小分词器:

preg_match_all('~/\*.*?\*/|//(?s).*|(example\.com)|.~', $code, $tokens, PREG_SET_ORDER);
foreach ($tokens as &$token) {
    if (strlen($token[1])) {
        $token = str_replace('example.com', 'example.net', $token[1]);
    } else {
        $token = $token[0];
    }
}
$code = implode('', $tokens);

请注意,这不考虑任何其他标记,如字符串。example.com因此,如果它出现在字符串中但也出现在“注释”中,则这将不匹配,例如:

'foo /* not a comment example.com */ bar'
于 2012-07-29T08:29:44.197 回答
2

仅当它不在注释部分内时才匹配的正则表达式example.com(但不关心行注释,因此您必须单独执行此操作):

$result = preg_replace(
    '%example\.com # Match example.com
    (?!            # only if it\'s not possible to match
     (?:           # the following:
      (?!/\*)      #  (unless an opening comment starts first)
      .            #  any character
     )*            # any number of times
     \*/           # followed by a closing comment.
    )              # End of lookahead
    %sx', 
    'newdomain.com', $subject);
于 2012-07-29T08:08:20.317 回答