在Perl中的一个正则表达式中存在两个字符串时替换字符串

时间:2017-08-18 18:21:35

标签: regex perl

给出以下输入

$ cat pre
stuff MACRO1 stuff MACRO2
stuff MACRO2 stuff MACRO1
stuff MACRO2 stuff

如果MACRO1也存在,我想替换MACRO2(与MACRO3)。像这样:

$ perl -ne '/(?=.*MACRO1).*MACRO2/ ? print s/MACRO2/MACRO3/gr : print' pre
stuff MACRO1 stuff MACRO3
stuff MACRO3 stuff MACRO1
stuff MACRO2 stuff

(我想这个表达式的.*MACRO2部分是不必要的,现在我想一想) 编辑。到目前为止,基于反馈的上述不那么愚蠢的版本:

$ perl -ne '/MACRO1/ ? print s/MACRO2/MACRO3/gr : print' pre

我想弄清楚的是如何只使用正则表达式来做到这一点。这是一次尝试:

$ perl -ne 'print s/(?=.*MACRO1)(?=.*MACRO2)MACRO2/MACRO3/gr' pre
stuff MACRO1 stuff MACRO2
stuff MACRO3 stuff MACRO1
stuff MACRO2 stuff

我认为我对先行运营商如何同时成为“锚”和“非消费”有一些根本的困惑。如果我认为?=是一个锚点,那么我认为上述方法不起作用。但这似乎与“非消费”相矛盾。

任何人都可以定义非消费的含义并向我展示一个可以产生预期结果的正则表达式吗?

2 个答案:

答案 0 :(得分:3)

首先,让我们得到实际的解决方案:

perl -pe's/MACRO2/MACRO3/g if /MACRO1/'

现在,让我们来看看你的特殊要求。作为单个替换,它将类似于以下内容:

perl -pe's/MACRO2(?:(?<=MACRO1.*)|(?=.*MACRO1))/MACRO3/g'

忽略这样的事实,因为不支持可变宽度的外观,这是无效的,这是非常低效的。虽然我提出的第一个解决方案所需的时间受文件大小的限制,但此解决方案所需的时间受文件大小的因子乘以MACRO2实例数的因子!

答案 1 :(得分:0)

然后总是:

$rec =~ s/^(.*)MACRO1(.*)MACRO2(.*)$/\1MACRO1\2MACRO3\3/;

O.k。,每条评论(如果MACRO2首先出现的话):

sub foo {
    my ($x) = @_;
    $x =~ s/2/3/;
    return $x;
}

然后:

$s3 =~ s/^(.*)((MACRO1(.*)MACRO2)|(MACRO2(.*)MACRO1))(.*)$/$1.($3?foo($3):foo($5))/e;

当然,这需要函数(我称之为foo)。

可以在没有函数的情况下完成,在替换模式中嵌套匹配/替换来做同样的事情,但是我从Perl得到了很多语法悲伤(我的错,我确定)。