Perl & Regex:仅当字符串不在 > 和 < 之间时才替换字符串
Perl & Regex: replace string only if it is not between > and <
我想替换>
和<
之间的所有字符串,例如,将center
(摘自:> is the sun the center of the universe?:<
)替换为foo,但不要替换 center
(摘自:<...center;">
)。
我正在使用以下命令:
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/(?<![\w$<])$\(center\)(?![\w$>])/foo/g;' file.html
但它不能正常工作我想要的。我在网上搜索了一下,最接近我需要的是 , and 。但是我不能完全解决只替换不是 <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 解决方案:
每当 <> 和 <> 之间有一个行跳转时,代码就会失败。例如,当要替换的单词像(这里有一个换行符)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{>\K[^<]*?\K.foo[^<]*(?=<).}{ bar }g;' file.html
或 perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo.[^<]*(?=<).}{ bar }g;' file.html
,这对换行有效,但它会删除 foo 之后的所有内容。我尝试了几种方法来避免删除 foo 后的文本,但我一直无法获得解决方案。如果万一我设法解决了这个问题,那么这个问题就会得到完整的回答。
编辑更新 02:
我现在已经将我在 EDIT UPDATE 01 中的修改从 Lordadmira 更改为 perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo.[^<](?!=<)}{ bar }g;'
以更正 foo 之后的文本之前被删除的事实。但这是擦除 foo
之后字符串的第一个字符,我想说例如在
> "lorem
foo ipsum "<
当 foo
被替换时,结果不是预期的,因为我得到 >" lorem bar psum "<
,也就是说, ipsum "i" 被删除了.
下面的解决方案解决了每次替换删除 foo 后字符串中有一个字符的问题。目前,在广泛的背景下,这是对 Lordadmira 初始解决方案的最实用的改编。
要解决此问题,需要省略 foo 末尾的运算符点,并在 Regex matching line not containing the string and exhaustively subsidized in the section "Positive and Negative Lookahead" 处添加否定先行作为附加解释,
将 (?=<)
属于 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
我的回答是对上面初始@lordadmira 解决方案的明显改编:
有两件事是促进 Lordadmira 最初解决方案的改编所必需的:使用分界线并在 foo 之后完整保留原始文本。改编如下:
perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo[^<](?!=<)}{ bar }g;'
要解决此问题,需要在 ..\K.foo
的末尾省略 运算符点 ,并在 Regex matching line not containing the string and exhaustively subsidized in the section "Positive and Negative Lookahead" 处添加否定前瞻作为附加解释,
将 (?=<)
属于 Lordadmira 的初始解决方案 的部分修改为 (?!=<)
.
注意:我不确定它是否适用于所有可能的代码格式或 html 内容上下文,但在我目前所做的测试中已经足够了。
最终解决方案(即在我上面的问题中编辑更新 3):
perl -0777 -pi -w -e 's{>[^<]*?\K\b(foo)\b(?!=<)}{bar}g;'
我想替换>
和<
之间的所有字符串,例如,将center
(摘自:> is the sun the center of the universe?:<
)替换为foo,但不要替换 center
(摘自:<...center;">
)。
我正在使用以下命令:
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/(?<![\w$<])$\(center\)(?![\w$>])/foo/g;' file.html
但它不能正常工作我想要的。我在网上搜索了一下,最接近我需要的是 <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 解决方案:
每当 <> 和 <> 之间有一个行跳转时,代码就会失败。例如,当要替换的单词像(这里有一个换行符)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{>\K[^<]*?\K.foo[^<]*(?=<).}{ bar }g;' file.html
或 perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo.[^<]*(?=<).}{ bar }g;' file.html
,这对换行有效,但它会删除 foo 之后的所有内容。我尝试了几种方法来避免删除 foo 后的文本,但我一直无法获得解决方案。如果万一我设法解决了这个问题,那么这个问题就会得到完整的回答。
编辑更新 02:
我现在已经将我在 EDIT UPDATE 01 中的修改从 Lordadmira 更改为 perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo.[^<](?!=<)}{ bar }g;'
以更正 foo 之后的文本之前被删除的事实。但这是擦除 foo
之后字符串的第一个字符,我想说例如在
> "lorem
foo ipsum "<
当 foo
被替换时,结果不是预期的,因为我得到 >" lorem bar psum "<
,也就是说, ipsum "i" 被删除了.
下面的解决方案解决了每次替换删除 foo 后字符串中有一个字符的问题。目前,在广泛的背景下,这是对 Lordadmira 初始解决方案的最实用的改编。
要解决此问题,需要省略 foo 末尾的运算符点,并在 Regex matching line not containing the string and exhaustively subsidized in the section "Positive and Negative Lookahead" 处添加否定先行作为附加解释,
将 (?=<)
属于 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
我的回答是对上面初始@lordadmira 解决方案的明显改编:
有两件事是促进 Lordadmira 最初解决方案的改编所必需的:使用分界线并在 foo 之后完整保留原始文本。改编如下:
perl -0777 -pi -w -e 's{>\K[^<]*?\K.foo[^<](?!=<)}{ bar }g;'
要解决此问题,需要在 ..\K.foo
的末尾省略 运算符点 ,并在 Regex matching line not containing the string and exhaustively subsidized in the section "Positive and Negative Lookahead" 处添加否定前瞻作为附加解释,
将 (?=<)
属于 Lordadmira 的初始解决方案 的部分修改为 (?!=<)
.
注意:我不确定它是否适用于所有可能的代码格式或 html 内容上下文,但在我目前所做的测试中已经足够了。
最终解决方案(即在我上面的问题中编辑更新 3):
perl -0777 -pi -w -e 's{>[^<]*?\K\b(foo)\b(?!=<)}{bar}g;'