Regex-嵌套模式-在外部模式中,但不包括内部模式



我有一个包含以下内容的文件。

<td> ${ dontReplaceMe } ReplaceMe ${dontReplaceMeEither} </td>

如果"ReplaceMe"在td标记中,我希望匹配它,但如果它在${…}表达式中,则不匹配。

我可以用regex做这件事吗?

目前有:

sed '/${.*?ReplaceMe.*?}/!s/ReplaceMe/REPLACED/g' data.txt

这是不可能的

Regex可用于第3类乔姆斯基语言(常规语言)
但是,您的示例代码是类型2的乔姆斯基语言(上下文无关语言)。

几乎只要涉及到任何类型的嵌套(括号),您就要处理无上下文的语言,而这些语言不在正则表达式中。

基本上没有办法在正则表达式中定义within a pair of x and y,因为这将要求正则表达式具有某种堆栈,而它没有(在功能上等效于有限状态自动机)。


brandizzi要求找到一个正则表达式,该正则表达式至少可以匹配琐碎的情况
事实上,我想出了这个(令人痛苦的)正则表达式模式:

perl -pe 's/(?<=<td>)((?:(?:{.*?})*[^{]*?)*)(ReplaceMe)(.*)(?=</td>)/$1REPLACED$3/g'

对这些情况进行适当的(原文如此!)匹配

<td> ${ dontReplaceMe } ReplaceMe ${dontReplaceMeEither} </td>
<td> ReplaceMe ${dontReplaceMeEither} </td>
<td> ${ dontReplaceMe } ReplaceMe </td>
<td> ReplaceMe </td>

失败了(嵌套是Chomsky Type-2,还记得吗?):

<td>${ ${ dontReplaceMe } ReplaceMe ${dontReplaceMeEither} }</td>

而且它也不能替换多个匹配:

<td> ReplaceMe ReplaceMe </td>
<td> ReplaceMe ${dontReplaceMeEither} ReplaceMe </td>

让领先的$覆盖是一个棘手的部分
这是为了防止雷金纳德/雷吉在写这只野兽时不断崩溃。

再说一遍:实验性的,永远不要在生产代码中使用这个

(…否则我会找到你,如果我必须使用你的代码/应用程序;)

对于这种简单的情况,您只需要验证行与${.*}:不匹配

$ sed '/${.*}/!s/ReplaceMe/REPLACED/' input
<td> REPLACED </td>
<td> ${ don't ReplaceMe } </td>

CCD_ 5 sed地址之后的CCD_。

OTOH,如果情况不是那么简单,我怀疑你的问题会增加很多,regex不会是最好的解决方案。

当涉及结构化标记时,通常使用regex是个坏主意。在某些特殊情况下,这可能是可以的,但有更好的工具来解析html和,然后您可以在文本节点上使用regex。

如果grep支持负lookbehinds(我不记得它是否支持),那么像<td>.*(?<!${).*ReplaceMe(?!.*}).*</td>这样的东西应该可以工作。

sed -i 's/<td>sReplaceMes</td>/<td>Replaced</td>/gi' input.file

为我工作。

您可以考虑使用-i.bak来备份旧文件,以防出现错误。

或者,

perl -pi -e 's/<td>sReplaceMes</td>/<td>Replaced</td>/g' temp

同样有效,再次注意要备份的-pi.bak。

最新更新