我有一个包含以下内容的文件。
<td> ${ dontReplaceMe } ReplaceMe ${dontReplaceMeEither} </td>
如果它在td标记中,我想匹配'ReplaceMe',但如果它在$ {...}表达式中则不匹配。
我可以使用正则表达式吗?
目前有:
sed '/\${.*?ReplaceMe.*?}/!s/ReplaceMe/REPLACED/g' data.txt
答案 0 :(得分:9)
这是不可能的。
正则表达式可用于 Type-3 Chomsky语言(常规语言)。
但是,您的示例代码是 Type-2 Chomsky语言(无上下文语言)。
几乎只要涉及任何类型的嵌套(括号),您就会处理无上下文的语言,这些语言不包括在正则表达式中。
基本无法在正则表达式中定义within a pair of x and y
,因为这会需要常规表达式有某种堆栈,它不是(在功能上等同于有限状态自动机)。
被brandizzi挑战,找到一个可能至少与琐碎案件相匹配的正则表达式
我实际上想出了这个(痛苦的hacky)正则表达式模式:
perl -pe 's/(?<=<td>)((?:(?:\{.*?\})*[^{]*?)*)(ReplaceMe)(.*)(?=<\/td>)/$1REPLACED$3/g'
对于这些情况做正确的 (sic!) 匹配:
<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>
获得领先的$
是最棘手的部分
这使得Reginald / Reggy在写这个野兽时不断崩溃。
(...或者我会追捕你,我是否必须使用您的代码/应用程序;)
答案 1 :(得分:1)
嗯,对于这种简单的情况,您只需要验证行 ${.*}
:
$ sed '/\${.*}/!s/ReplaceMe/REPLACED/' input
<td> REPLACED </td>
<td> ${ don't ReplaceMe } </td>
!
sed地址之后的/\${.*}/
会否定标准。
答案 2 :(得分:1)
通常在涉及结构化标记时使用正则表达式是个坏主意。在某些特殊情况下它可能没问题,但有更好的工具来解析html和然后你可以在文本节点上使用正则表达式。
答案 3 :(得分:0)
像<td>.*(?<!${).*ReplaceMe(?!.*}).*</td>
这样的东西应该有效,如果grep支持负面的看守(我不记得是否会这样做)。
答案 4 :(得分:0)
sed -i 's/<td>\sReplaceMe\s<\/td>/<td>Replaced<\/td>/gi' input.file
为我工作。
如果出现错误,您可以考虑使用-i.bak备份旧文件。
或者,
perl -pi -e 's/<td>\sReplaceMe\s<\/td>/<td>Replaced<\/td>/g' temp
也可以,再次注意-pi.bak备份。