4

我正在尝试查找可能出现在注释块内的某个字符串。该字符串可以是一个词,但它也可以是一个词的一部分。例如,假设我正在寻找“codex”这个词,那么这个词应该替换为“bindex”,但即使它是一个词的一部分,比如“codexing”。这应该更改为“bindexing”。

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

/* 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”前面的所有文本。

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

4

5 回答 5

3

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

试试这个代码:

$text = preg_replace ( '~(//|#|/\*).*?(codex).*?~s', '$1 bindex', $text );
于 2013-08-05T20:01:44.523 回答
2
$text = preg_replace ( '~(//|#|/\*)(.*?)(codex).*?~s', '$1$2bindex', $text );

这不会像 anubhava 的回答那样删除“codex”之前的评论

于 2013-08-05T20:22:35.413 回答
1

[编辑] 我编辑了这个答案,因为尽管当时我天真无情,但我还是决定承认,用简单或复杂的方式解决这个问题是不可能的preg_replace!对支持我的回答的好人深表歉意。[/编辑]

回答这个问题:改善你的模式是不可能的,根本不可能做到这一点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);

请注意,除了这种模式更简单之外,它也很有效,因为交替的每个分支都是“锚定的”,因为它们以文字字符开头。因此,该模式受益于自动优化。

于 2013-08-05T21:40:07.387 回答
0

像这样使用子组的东西应该可以工作;

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

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

于 2013-08-05T19:57:14.313 回答
0

正如之前在不同评论中所写的数百、数千甚至数百万次一样,正则表达式不适用于解析代码或在其中搜索错误。

考虑这些例子:

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

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

您无法使用 REGEX 解析代码(是的,找出字符串是否在注释块内称为解析)。

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

于 2013-08-05T20:00:09.367 回答