【问题标题】:Perl & Regex: replace string only if it is not between > and <Perl & Regex:仅当字符串不在 > 和 < 之间时才替换字符串
【发布时间】:2021-06-02 19:02:36
【问题描述】:

我想替换&gt;&lt;之间的所有字符串,例如用foo替换center(摘自:&gt; is the sun the center of the universe?:&lt;),但不要替换center(摘自:&lt;...center;"&gt;)。

我正在使用以下命令:

perl -pi -w -e 's/center/foo/g;' file.html

所以我尝试使用replace all "foo" between two HTML tags using REGEX (PHP code),变成这样:

perl -pi -w -e 's/(?&lt;![\w$&lt;])\$\(center\)(?![\w$&gt;])/foo/g;' file.html

但它不能正常工作。我在网上搜索,最接近我需要的是Perl string replace: Match, but not replace, part of regexPerl Regex - Search and replace between tags only if string is in-betweenReplace text in string with exceptions。但是我不能完全解决只替换不是&lt;center&gt; 的字符串的需要。

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 解决方案

每次和>之间有换行,代码就会失败。例如当要替换的单词像(这里有一个换行符)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 解决方案 修改为 perl -0777 -pi -w -e 's{&gt;\K[^&lt;]*?\K.foo[^&lt;]*(?=&lt;).}{ bar }g;' file.htmlperl -0777 -pi -w -e 's{&gt;\K[^&lt;]*?\K.foo.[^&lt;]*(?=&lt;).}{ bar }g;' file.html,这适用于换行符,但它会删除 foo 之后的所有内容。我尝试了几种方法来避免删除 foo 后的文本,但我一直无法得到解决方案。如果我设法解决了这个问题,那么问题将得到充分回答。

编辑更新 02

我现在已将我的修改从 EDIT UPDATE 01 中的 Lordadmira 更改为 perl -0777 -pi -w -e 's{&gt;\K[^&lt;]*?\K.foo.[^&lt;](?!=&lt;)}{ bar }g;',以纠正 foo 之后的文本之前已被删除的事实。但是这是删除foo之后的字符串的第一个字符,我想说例如在

> "lorem
  foo ipsum "< 

foo被替换时,结果不是预期的,因为我得到&gt;" lorem bar psum "&lt;,即ipsum "i"被删除


下面的解决方案解决了每次替换删除 foo 后字符串中有字符的问题。目前,在广泛的背景下,这是对 Lordadmira 最初解决方案最实用的改编。

为了解决这个问题,有必要在 foo 的末尾省略操作符点,并在Regex matching line not containing the string 处添加负前瞻作为附加解释,并在"Positive and Negative Lookahead" 部分进行详尽的补贴, 将属于Lordadmira的初始解决方案的部分(?=&lt;)修改为(?!=&lt;)

perl -0777 -pi -w -e 's{&gt;\K[^&lt;]*?\K.foo[^&lt;](?!=&lt;)}{ bar }g;'


编辑更新 3:

经过多次测试,我相信我的意图已经达到了最令人满意的解决方案。

perl -0777 -pi -w -e 's{>[^

【问题讨论】:

  • perl -pi -w -e 's/(?&lt;=&gt;)[^&lt;]+(?=&lt;)/foo/g;' file.html 呢,还是需要专门匹配“center”?
  • @JerryJeremiah,至于指定中心,它仅适用于 fragment_code_html 与 MWE 一起服务,但我也需要替换 center 周围的许多其他字符串。尽管更好地考虑中心周围是否存在其他字符串可能会影响解决方案。

标签: html perl html-parsing


【解决方案1】:

你会这样做的。

s{>\K[^<]*?center[^<]*(?=<)}{foo}g;

编辑:使用perl -p 命令行逐行读取文件,并假定您要执行的所有工作都包含在单行中。如果您需要跨行工作,则必须读取整个文件(或任何足够的块)。使用perl -0777 -p,它应该可以工作。

更多信息请参见perlrun

HTH

【讨论】:

  • 每次&lt;&gt; and &lt;/&gt;之间有行跳转,代码都会失败。例如,当要替换的单词是 &lt;tr&gt; (here there is a line break) center &lt;/&gt; 时失败。会发生什么?
  • 当您使用-p 开关时,它会逐行读取文件。如果匹配中可能存在换行符,请立即读入整个文件。要么将-0777 放在命令行上,要么编写一个简短的脚本和undef $/
  • perl -0777 -p 不起作用,我阅读了 perlrun 中的文档并研究了网络,但没有任何问题得到解决。这里有一个示例github.com/yaacovNaNachRabbeinu/things/blob/main/…,在这个文件中我想用luz替换例如light,但是当我运行perl -0777 -pi -e 's{&gt;k[^]*?light[^&lt;]*?=&lt;)}{light}g;'Alexandrite.html时文本没有改变。
  • 事实上,命令 'perl -0777 -pi -e 's{&gt;k[^]*?light[^&lt;]*?=&lt;)}{light}g;'Alexandrite_mini.txt 即使文件不是 HTML 并且有一个简短的文本作为这个文件 github.com/yaacovNaNachRabbeinu/things/blob/main/… 也不起作用
  • 我已将其初始解决方案修改为 perl -0777 -pi -w -e 's{&gt;\K[^&lt;]*?\K.foo[^&lt;]*(?=&lt;).}{ bar }g;' file.htmlperl -0777 -pi -w -e 's{&gt;\K[^&lt;]*?\K.foo.[^&lt;]*(?=&lt;).}{ bar }g;' file.html,这适用于换行符,但它会删除 foo 之后的所有内容。我尝试了几种方法来避免删除 foo 后的文本,但我一直无法得到解决方案。如果万一我设法解决了这个问题,那么问题将得到充分回答..
【解决方案2】:

我的回答显然是对上面最初的@lordadmira 解决方案的改编:

促进对 Lordadmira 最初解决方案的改编需要两件事:使用换行符并在 foo.改编如下:

perl -0777 -pi -w -e 's{&gt;\K[^&lt;]*?\K.foo[^&lt;](?!=&lt;)}{ bar }g;'

要解决这个问题,有必要在..\K.foo 的末尾省略operator dot,并在Regex matching line not containing the string 处添加负前瞻作为附加解释,并在"Positive and Negative Lookahead" 部分进行详尽的补贴, 将属于Lordadmira的初始解决方案的部分(?=&lt;)修改为(?!=&lt;)

注意:我不确定它是否适用于所有可能的代码格式或 html 内容上下文,但在我迄今为止所做的测试中已经足够了。

最终解决方案(即上面我的问题中的 EDIT UPDATE 3):

perl -0777 -pi -w -e 's{>[^

【讨论】:

    猜你喜欢
    • 2021-09-29
    • 2016-02-18
    • 1970-01-01
    • 2021-03-11
    • 2017-07-13
    • 2012-08-11
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多