我上一篇文章的标签被部分剥离了,所以这里又是:
我的目标是将所有尾随实例替换为标记括号内的尾随+。让我们假设要替换的行如下所示:
<h> aa- aa- </h> <h> ba- ba- </h>
然后应该看起来像
<h> aa+ aa+ </h> <h> ba+ ba+ </h>.
首先我尝试了这个表达式:
s/<h>(.*?)-(.*?)<\/h>/<h>$1+$2<\/h>/g;
产生了这个输出:
<h> aa+ aa- </h> <h> ba+ ba- </h>.
g选项确实会导致每行有多个替换,但仅限于每个标记括号的第一个实例(并且仅当两个圆括号都包含问号时)。
为了缩小问题范围,我接着尝试了无视标签来实现替换。表达式
s/(.*?)-(.*?)/$1+$2/g;
确实导致了期望的结果
<h> aa+ aa+ </h> <h> ba+ ba+ </h>.
当然,这也会替换标签括号以外的内容。
那么我的第一个表达式出现了什么问题,如何在标记括号内实现完全替换的目标?
答案 0 :(得分:0)
1)g选项适用于整个正则表达式包含标签
2)使用它两次或直到没有变化
答案 1 :(得分:0)
分隔标签选择和替换操作:
$str = '<h> aa- aa- </h> <h> ba- ba- </h>';
while ( $str =~ m!<h>.*?-.*?</h>! ) {
substr( $str, $-[0], $+[0] - $-[0] ) =~ y/-/+/;
}
print $str, "\n";
(@-
和@+
数组提供有关上次成功匹配的偏移信息。)
可替换地:
sub fixup_h_tag {
my $tag = shift;
$tag =~ y/-/+/;
$tag
}
$str = '<h> aa- aa- </h> <h> ba- ba- </h>';
$str =~ s{ (<h>.*?</h>) }{ fixup_h_tag("$1") }gxe;
print $str, "\n";
请注意,如果您的标记标记语言允许使用某种类型的注释或带引号的字符串(可能包含或不包含标记)或h标记中的可选空格或属性,则正则表达式不容易提供强大的解决方案。