Perl:标记分隔字符串中的全局替换

时间:2010-08-01 12:11:44

标签: xml perl replace tags substitution

我上一篇文章的标签被部分剥离了,所以这里又是:

我的目标是将所有尾随实例替换为标记括号内的尾随+。让我们假设要替换的行如下所示:

<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>.

当然,这也会替换标签括号以外的内容。

那么我的第一个表达式出现了什么问题,如何在标记括号内实现完全替换的目标?

2 个答案:

答案 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标记中的可选空格或属性,则正则表达式不容易提供强大的解决方案。