[英]Regex: Match a substring in all lines, except when the substring is inside a comment section
我来啦:
我正在编写一个PHP应用程序,我有一个新的官方域名,现在所有的FAQ都在这里。 我脚本中的一些文件包含旧FAQ域的帮助链接,因此我想使用新域替换它们。 但是,我想保留链接到旧域的URL,只要它们位于注释或注释块下面(我仍然使用旧域进行自我引用和其他文档)。
所以,基本上,我想要实现的是一个正则表达式,它具有以下功能:
example.com
的所有匹配项*。 example.com
字符串。 //
, /*
或“*”开头,则不匹配该单行中的任何example.com
实例(但是,如果注释块在打开它的同一行中关闭,则可能会出现问题)。 我经常写这样的块评论:
/* text
* blah
* blah
*/
这就是为什么我不想匹配“example.com”,如果它位于//
, /*
或“*”之后。
我想它会是这样的:
^(?:(?!//|/\*|\s\*).?).*example\.com
但是这有一个问题:它匹配整行,而不仅仅是“example.com”(这会导致问题,主要是当两个或多个“example.com”字符串在一行中匹配时)。
有人可以帮我修复我的正则表达式吗? 请注意:它不一定是PHP正则表达式,因为我总是可以使用像grepWin这样的工具来一次本地编辑所有文件。
哦, 请告诉我是否有办法以某种方式概括块注释,例如:找到/*
在找到*/
之前不匹配example.com
。 那将非常有用。 是否有可能实现一般(非语言相关)正则表达式?
一个正则表达式只匹配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);
我会使用某种标记器来区分评论和其他语言标记。
在处理PHP文件时,您应该使用PHP自己的tokenizer函数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'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.