提问人:7beggars_nnnnm 提问时间:3/4/2021 最后编辑:7beggars_nnnnm 更新时间:3/15/2021 访问量:396
Perl & Regex:仅当字符串不在 > 和 < 之间时才替换字符串
Perl & Regex: replace string only if it is not between > and <
问:
我想替换 和 之间的所有字符串,例如,将 (from excerpt:) 替换为 foo,但不要替换 (from excerpt: )。>
<
center
> is the sun the center of the universe?:<
center
<...center;">
我正在使用以下命令:
perl -pi -w -e 's/center/foo/g;' file.html
因此,我尝试使用REGEX(PHP代码)在两个HTML标签之间替换所有“foo”,得到如下结果:
perl -pi -w -e 's/(?<![\w$<])\$\(center\)(?![\w$>])/foo/g;' file.html
但它不能正常工作。我在网上搜索了一下,最接近我需要的是 Perl 字符串替换:匹配,但不替换正则表达式的一部分,Perl 正则表达式 - 仅当字符串介于两者之间时,才在标签之间搜索和替换,并且用异常替换字符串中的文本。但是我不能完全解决仅替换非特定字符串的需要。<center>
fragment_html_code:
</td></tr><tr><th colspan="2" class="" style="text-align:center;">is the sun the center of the universe?:</th></tr><tr class=""><td colspan="2" class="" style="text-align:center;">
center </td></tr>
编辑更新:
关于Lordadmira Solution:
每次在 <> 和 </> 之间出现跳线时,代码都会失败。例如,当要替换的单词是 like(这里有一个换行符)center </> 时失败。它可能会发生什么?有关上下文示例,请参阅下文:
</td></tr><tr><th colspan="2" class="" style="text-align:center;">
(Here there is a line jump and then the solution of Lordadmira fails and does not occur) ----> is the sun the center of the universe?:
</th></tr><tr class=""><td colspan="2" class="" style="text-align:center;">
center </td></tr>
编辑更新01:
我将 Lordadmira 的初始解决方案修改为 or,这适用于换行符,但它删除了 foo 之后的所有内容。在删除 foo 后,我尝试了几种方法来避免文本,但一直无法得到解决方案。如果我设法解决了这个问题,那么这个问题将得到充分的回答。perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo[^<]*(?=<).}{ bar }g;' file.html
perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo.[^<]*(?=<).}{ bar }g;' file.html
编辑更新02:
我现在已将我在 EDIT UPDATE 01 中从 Lordadmira 的修改更改为更正之前删除了 foo 之后的文本这一事实。但这是擦除字符串的第一个字符之后,我想说的是,例如在perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo.[^<](?!=<)}{ bar }g;'
foo
> "lorem
foo ipsum "<
当被替换时,结果不符合预期,因为我得到,即 ipsum “i” 被删除。foo
>" lorem bar psum "<
下面的解决方案解决了每次替换删除 foo 后字符串中有一个字符的问题。就目前而言,在广泛的背景下,这是对Lordadmira最初解决方案的最有效的改编。
为了解决这个问题,有必要省略 foo 末尾的运算符点,并在不包含字符串的正则表达式匹配行添加负前瞻作为附加解释,并在“正负前瞻”部分中详尽地补贴,
将属于 Lordadmira 初始解的部分修改为 。(?=<)
(?!=<)
perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo[^<](?!=<)}{ bar }g;'
编辑更新 3:
经过几次测试,我相信已经为我的意图找到了最令人满意的解决方案。
perl -0777 -pi -w -e 's{>[^<]*?\K\b(foo)\b(?!=<)}{bar}g;'
答:
你会这样做的。
s{>\K[^<]*?center[^<]*(?=<)}{foo}g;
编辑:使用命令行逐行读取文件,并假定要执行的所有工作都包含在单行中。如果你需要跨行工作,你必须读入整个文件(或任何足够的块)。使用,它应该可以工作。perl -p
perl -0777 -p
有关更多信息,请参见 perlrun。
HTH
评论
<> and </>
<tr> (here there is a line break) center </>
-p
-0777
undef $/
perl -0777 -p
没有用,我阅读了 perlrun 中的文档并研究了网络,但没有任何解决。这里有一个示例 github.com/yaacovNaNachRabbeinu/things/blob/main/...,,在这个文件中,我想替换例如,但是当我运行Alexandrite.html时,文本没有改变。light
luz
perl -0777 -pi -e 's{>k[^]*?light[^<]*?=<)}{light}g;'
'perl -0777 -pi -e 's{>k[^]*?light[^<]*?=<)}{light}g;'
perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo[^<]*(?=<).}{ bar }g;' file.html
perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo.[^<]*(?=<).}{ bar }g;' file.html
我的回答显然是对上面最初的@lordadmira解决方案的改编:
为了促进对Lordadmira最初解决方案的改编,有两件事是必要的:使用断行符,并在foo之后保持原始文本的完整。改编如下:
perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo[^<](?!=<)}{ bar }g;'
为了解决这个问题,有必要省略 末尾的运算符点 ,并在“正负展望”一节中添加负前瞻作为附加解释,该行不包含字符串并详尽地补贴,
将属于 Lordadmira 初始解的部分修改为 。..\K.foo
(?=<)
(?!=<)
注意:我不确定它是否适用于代码格式或html内容的所有可能上下文,但在我迄今为止所做的测试中已经足够了。
解决方案最终(即我上面问题中的 EDIT UPDATE 3):
perl -0777 -pi -w -e 's{>[^<]*?\K\b(foo)\b(?!=<)}{bar}g;'
评论
perl -pi -w -e 's/(?<=>)[^<]+(?=<)/foo/g;' file.html
fragment_code_html
center