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

zzx*_*xyz 5 regex perl

鉴于以下输入

$ cat pre
stuff MACRO1 stuff MACRO2
stuff MACRO2 stuff MACRO1
stuff MACRO2 stuff
Run Code Online (Sandbox Code Playgroud)

如果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
Run Code Online (Sandbox Code Playgroud)

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

$ perl -ne '/MACRO1/ ? print s/MACRO2/MACRO3/gr : print' pre
Run Code Online (Sandbox Code Playgroud)

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

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

我认为我对前瞻操作员如何同时成为"锚"和"非消费"都有一些根本的困惑.如果我把?=它想象成一个锚点,那对我来说上述不起作用是有意义的.但这似乎与"非消费"相矛盾.

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

ike*_*ami 3

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

perl -pe's/MACRO2/MACRO3/g if /MACRO1/'
Run Code Online (Sandbox Code Playgroud)

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

perl -pe's/MACRO2(?:(?<=MACRO1.*)|(?=.*MACRO1))/MACRO3/g'
Run Code Online (Sandbox Code Playgroud)

忽略这个不起作用的事实,因为不支持可变宽度后向查找,这是非常低效的。虽然我提出的第一个解决方案所需的时间受文件大小的影响,但该解决方案所需的时间受文件大小乘以 MACRO2 实例数量的影响!

  • `/c(?=a)(?=b)/` 是否更清楚?请记住,所有匹配项前面都有隐式的“\A(?s:.)*?”。不存在紧接着“a”且紧接着“b”的位置。 (2认同)