我想在字符串中进行多次替换,但只能在start regex和end regex之间进行。例如:
$ start = qr / a。*?b /;$ end = qr / c。*?d /;$ string =’a1b x c2d x a345b ……
您需要全局替换但仅在标记模式中的复杂性可以通过捕获该子字符串并在替换部分中对其运行正则表达式来处理
my $s = q(a1b x and x c2d x more x a22b x again x c33d x and x); $s =~ s/a.*?b\K(.*?)(?=c.*?d)/$1=~s{x}{y}gr/eg; say $s;
我用 \K 在左标记图案之后( a.*?b )删除先前的匹配和前标记的右标记模式( c.*?d ),所以不要复制那些,但为了简单起见,你可以捕获它们并使用数字变量( $N )为他们取代。
\K
a.*?b
c.*?d
$N
如果模式重复,请考虑捕获正确的标记(而不是前瞻);然后,对于额外的数据复制,子模式不会重复扫描,整体正则表达式更清晰,原则上更安全(右标记可能包含左标记吗?)。这确实使更换部件复杂化,其中 $2 需要在新的正则表达式之前保存,因为它在其中被重置。
$2
请注意 /r 更换部件的正则表达式中的修饰符:除了非常方便之外,它还允许我们使用 s/// 在...上 $1 变量,否则我们不能做,因为它是只读的。
/r
s///
$1
如果这是更复杂的正则表达式处理的一部分,请注意前瞻是零宽度 断言 所以引擎不消耗该模式并且不通过它。如果整个模式重复,则这很重要:如果右标记可能包含左标记,则必须捕获它以使引擎移动经过它以进行下一次匹配,以便左标记首先出现。
这适用于标记模式的变量,您可以很好地使用它们
my $start = qr/a.*?b/; my $end = qr/c.*?d/; my $s = q(a1b x and x c2d x more x a22b x again x c33d x and x); $s =~ s/$start\K (.*?) (?=$end)/ $1 =~ s{x}{y}gr /egx; say $s;
由于礼貌,我在那里间隔图案以便于阅读 /x 。它打印
/x
a1b y and y c2d x more x a22b y again y c33d x and x
你可以使用 /e 修改为执行代码(分别为每个匹配)生成替换字符串:
/e
use strict; use warnings; my $start_regex = qr/a.*?b/; my $end_regex = qr/c.*?d/; my $string = 'a1b x c2d x a345b qqxxxc678d xx abxcd'; $string =~ s/($start_regex)(.*?)($end_regex)/ my ($start_match, $middle_match, $end_match) = ($1, $2, $3); $middle_match =~ s!x!y!g; $start_match . $middle_match . $end_match /eg; print $string, "\n";
将打印出来
a1b y c2d x a345b qqyyyc678d xx abycd
请注意备用正则表达式分隔符 s!!! 在内部正则表达式。
s!!!
存储它是很重要的 $1 , $2 和 $3 临时变量中的外部正则表达式匹配,因为当您在替换代码中执行另一个正则表达式时它们将丢失。
$3