1

我之前的帖子部分去掉了标签,所以又是这样:

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

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

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

那么我的第一个表达式有什么问题,我怎样才能实现在标签括号内完全替换的目标?

4

2 回答 2

0

分离标签选择和替换操作:

$str = '<h> aa- aa- </h> <h> ba- ba- </h>';
while ( $str =~ m!<h>.*?-.*?</h>! ) {
    substr( $str, $-[0], $+[0] - $-[0] ) =~ y/-/+/;
}
print $str, "\n";

@-and@+数组提供关于最后一次成功匹配的偏移信息。)

或者:

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

于 2010-08-01T17:14:30.427 回答
0

1) g 选项适用于包含标签的整个正则表达式

2)使用它两次或直到没有变化

于 2010-08-01T12:25:35.533 回答