用正则表达式查找并替换注释块中的字符串(的一部分)


Find and replace (part of) string in comment blocks with regex

我试图找到一个可以出现在注释块中的特定字符串。这个字符串可以是一个单词,但也可以是单词的一部分。例如,假设我在寻找单词"codex",那么这个单词应该被替换为"bindex",但即使它是单词的一部分,比如"codexing"。这应该改为"绑定"。

诀窍是,只有当这个词在注释块内时,才会发生这种情况。

/* Lorem ipsum dolor sit amet, codex consectetur adipiscing elit. */
This word --> codex should not be replaced
/* Lorem ipsum dolor sit 
 * amet, codex consectetur 
 * adipiscing elit. 
 */
/** Lorem ipsum dolor sit 
 * amet, codex consectetur 
 * adipiscing elit. 
 */
// Lorem ipsum dolor sit amet, codex consectetur adipiscing elit.
# Lorem ipsum dolor sit amet, codex consectetur adipiscing elit.
------------------- Below "codex" is part of a word -------------------
/* Lorem ipsum dolor sit amet, somecodex consectetur adipiscing elit. */
/* Lorem ipsum dolor sit 
 * amet, codexing consectetur 
 * adipiscing elit. 
 */
And here also, this word --> codex should not be replaced
/** Lorem ipsum dolor sit 
 * amet, testcodexing consectetur 
 * adipiscing elit. 
 */
// Lorem ipsum dolor sit amet, __codex consectetur adipiscing elit.
# Lorem ipsum dolor sit amet, codex__ consectetur adipiscing elit.

到目前为止,我有这个代码:

$text = preg_replace ( '~('/'/|#|'/'*).*?(codex).*?~', '$1 bindex', $text);

正如你在这个例子中看到的,这并不是我想要的方式。当单词位于多行/* */注释块中时,它不会替换该单词,有时还会删除单词"codex"前面的所有文本。

如何改进我的正则表达式,使其满足我的要求?

由于您在这里处理的是多行文本,因此应该使用s修饰符(DOTALL)来匹配多行文本。此外,正斜杠不需要转义。

试试这个代码:

$text = preg_replace ( '~(//|#|/'*).*?(codex).*?~s', '$1 bindex', $text );
$text = preg_replace ( '~(//|#|/'*)(.*?)(codex).*?~s', '$1$2bindex', $text );

这不会删除"codex"之前的评论,就像在回答来自anubhava

[EDIT]我编辑了这个答案,因为尽管当时我很天真,但我决心承认,用简单或复杂的preg_replace都不可能解决这个问题!抱歉好心人投票支持我的回答。[/EDIT]

回答这个问题:不可能改进你的模式,根本不可能用preg_replace来做!您必须为preg_replace_callback构建一个匹配整个注释的模式,然后继续替换回调函数中出现的codex

此版本可以处理任何类型的注释,并且不会因使用此类字符串/**/ codex /**//*xxxx codex codex xxxx*/或任何其他陷阱而失败。

$result = preg_replace_callback('~/'*.*?'*/|#'N+|//'N+~s', function($m) {
    return stri_replace('codex', 'bindex', $m[0]);
}, $subject);

注意,除了这种模式更简单这一事实之外,它也是有效的,因为交替的每个分支都是"0";"锚定";因为它们是从字面字符开始的。因此,该模式受益于自动优化。

正如以前在不同的注释中写过数百、数千甚至数百万次一样,正则表达式不用于分析代码或在其中搜索错误。

考虑以下示例:

// code to be replaced
var a = "/*code to be replaced*/";
/* code to be replaced
var b = "*/code to be replaced"; */

使用REGEX无法解析代码(是的,发现字符串是否在注释块中称为解析)。

找到一个解析器库,或者创建一个自己的精简库。如果您确实创建了一个,请记住脚本的所有不同用例,特别是字符串将如何影响代码。

像这样使用子组的方法应该有效;

$str = preg_replace(
    '~(<!--[a-zA-Z0-9 'n]*)(MYWORD)([a-zA-Z0-9 'n]*-->)~s',
    '$1$3',
     $input
);

您只需要为每种类型的注释创建一个单独的规则,并用字符类限制注释中允许的可能字符(您可能更喜欢使用否定字符类)。