仅在Perl模式的匹配部分中替换

时间:2015-05-15 01:49:17

标签: regex perl pattern-matching

如何才能在匹配模式中替换并使用Perl将其放回同一个变量中?

例如:

my $str = "a.b.AA pat1 BB hgf AA pat1 BB jkl CC pat1 don't change pat1";

我想在pat1AA之间匹配BB,并将其替换为原始字符串PAT2。但是,我不想在同一个字符串中的任何其他位置替换pat1

预期输出字符串:

a.b.AA PAT2 BB hgf AA PAT2 BB jkl CC pat1 don't change pat1

我相信应该有一些好的方法来做到这一点;请指教。

原始字符串:

my $ORG_str = 'A.B.C.\\valid.A .\\valid.A.B.C .\\valid.X.Y.Z .p.q.r.s';

预期字符串:

my $EXP_op = 'A.B.C.\\valid?A .\\valid?A?B?C .\\valid?X?Y?Z .p.q.r.s';

将字符.替换为?,只有在反斜杠\和空格之间。

3 个答案:

答案 0 :(得分:3)

查看look-around regexes

s/(?<=AA )pat1(?= BB)/pat2/g

匹配并替换pat1AA所包围的BB

答案 1 :(得分:1)

\\\\[^. ]*\K|(?!^)\G\.([^. ]*)

你可以试试这个。?$1。见。演示。

https://regex101.com/r/mT0iE7/28

结果字符串与您想要的字符串不完全相同,但您可以轻松地进行清理。

\?(?=\?)

替换为empty string,你有你想要的。参见演示。

https://regex101.com/r/mT0iE7/29

答案 2 :(得分:1)

使用单个正则表达式并不是很简单,所以我使用了分而治之来计算结果。这是一个小的递归函数,正在取代单个&#39;。每组(&#39; \&#39;&#39;&#39;)

当没有要替换的内容时,迭代结束

sub replace {
    my ($input) = @_;

    my $result = $input;
    $result =~ s/(\\\S*?)\.(.*? )/$1?$2/g;
    return $result if $result eq $input;
    return replace($result);
}

包含一些测试用例的函数

use strict;

my $ORG_str= 'A.B.C.\\\\valid.A .\\\\valid.A.B.C .\\\\valid.X.Y.Z .p.q.r.s';
my $EXP_op ='A.B.C.\\\\valid?A .\\\\valid?A?B?C .\\\\valid?X?Y?Z .p.q.r.s';

sub replace {
    my ($input) = @_;

    my $result = $input;
    $result =~ s/(\\\S*?)\.(.*? )/$1?$2/g;
    return $result if $result eq $input;
    return replace($result);
}

my $check;
my $result;
my $expected;

$check = 'abcd'; $expected = $check;
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");

$check = 'ab\xxx. cd'; $expected = 'ab\xxx? cd';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");

$check = 'ab\x.x.x. cd'; $expected = 'ab\x?x?x? cd';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");

$check = 'ab\x.x.x. cd\y.y.y.'; $expected = 'ab\x?x?x? cd\y.y.y.';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");

$check = 'ab\x.x.x. cd\xxx.xxx..xxx...x \y.y.y.'; $expected = 'ab\x?x?x? cd\xxx?xxx??xxx???x \y.y.y.';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");

$check = '. ..\.. ...\.. ...\.. ...\..'; $expected = '. ..\?? ...\?? ...\?? ...\..';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");


$check = $ORG_str; $expected = $EXP_op; 
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");


sub assert {
    my ($cond, $mesg) = @_;
    print "checking $mesg ... ";
    die "\nFAIL: $mesg" unless $cond;
    print "OK\n";
}

结果

checking 'abcd' gives 'abcd' ... OK
checking 'ab\xxx. cd' gives 'ab\xxx? cd' ... OK
checking 'ab\x.x.x. cd' gives 'ab\x?x?x? cd' ... OK
checking 'ab\x.x.x. cd\y.y.y.' gives 'ab\x?x?x? cd\y.y.y.' ... OK
checking 'ab\x.x.x. cd\xxx.xxx..xxx...x \y.y.y.' gives 'ab\x?x?x? cd\xxx?xxx??xxx???x \y.y.y.' ... OK
checking '. ..\.. ...\.. ...\.. ...\..' gives '. ..\?? ...\?? ...\?? ...\..' ... OK
checking 'A.B.C.\\valid.A .\\valid.A.B.C .\\valid.X.Y.Z .p.q.r.s' gives 'A.B.C.\\valid?A .\\valid?A?B?C .\\valid?X?Y?Z .p.q.r.s' ... OK