2

感谢@cool_me5000 在这里帮助我解决了这个问题的过度简化版本:PERL: Using REGEX to match a string without the first token repeated in the string。(ABC,不是 AAA ABC)

这是调整后的问题:

我正在尝试使用正则表达式来匹配 ATE 后跟 CAT 的 FIRST 实例,而 ATE 和 CAT 之间没有另一个 ATE。我想匹配“ATE BAT CAT”。请注意,在此文本字符串中,在第一个 ATE/CAT 组合之后还有其他实例也可能适合 ATE/CAT,(特别注意字符串末尾附近的“ATE DOG CAT”)这是文本:

$TEXT = "ATE ATE ATE ATE BAT CAT ATE DOG EGG ATE FOR GIN ATE DOG CAT ATE";

我第一次尝试:

@finds1=$TEXT=~m/((ATE).*?(CAT))/;
$result = $finds1[0];
print "result = $result\n";

这将打印以下内容:

result = ATE ATE ATE ATE BAT CAT

当我想要的只是:

result = ATE BAT CAT

请注意,我正在尝试创建一个可以在 B 可以是任何字符串的情况下使用的正则表达式。例如 ATE DOG CAT、ATE FAT GET HAT JOT KIN CAT、ATE YAK ULE INN OLD KOC JOG HUG GOT TAL CAT。

接下来我尝试使用前瞻语句和 if then else 语句。这是代码:

@finds1=$TEXT=~m/(ATE(?(?!.*?ATE.*?CAT).*?CAT|Z{100}))/;
$result = $finds1[0];
print "result = $result\n";

REGEX 的第一部分,(ATE,告诉 perl 找到 ATE 的出现。一旦找到,perl 然后处理 if then else 语句,其中条件语句是在 ATE 之后没有 . ?ATE. ?CAT 的实例, 如果没有找到,则 perl 查找 .*?CAT,如果至少找到一个,则搜索 100 个 Z 实例。我试图解析有 100 个 Z。)

这将返回:

result = ATE DOG CAT    

在第一次识别 CAT 后,我考虑过使用积极的后视。但是,就像我上面提到的,第一个 ATE.CAT 组合之间没有 A 的字符数是可变的。据我所知,PERL 不能进行可变长度的后视。

非常感谢您提供的任何帮助或指导!

提前致谢!

4

1 回答 1

3

对于前面的问题,解决方案是:

my ($first) = $text =~ /(A[^AC]*C)/;

我们使用了A|Cthen 的否定,这意味着我们需要使用ATE|CAThere 的否定。

每个人都应该知道的是,(?:(?!STRING).)就是这样。也适用于一些更复杂的模式,包括上面的模式。(?:STRING)[^CHAR]CHAR(?:(?!PAT).)

所以我们得到:

my ($first) = $text =~ /(ATE (?:(?!ATE|CAT).)* CAT)/sx;

解释:

您不希望在“ATE”和“CAT”之间出现“CAT”或“ATE”,所以

   +---------------- You don't want CAT or ATE starting here.
   |+--------------- You don't want CAT or ATE starting here.
   ||--+------------ You don't want CAT or ATE starting here.
   ||   +----------- You don't want CAT or ATE starting here.
   ||   |+---------- You don't want CAT or ATE starting here.
   ||   ||
   vv   vv
ATE??...??CAT

所以那将是

/
   ATE
   (?! CAT|ATE ) .
   (?! CAT|ATE ) .
   ...
   (?! CAT|ATE ) .
   (?! CAT|ATE ) .
   CAT
/x

使用 处理重复*

于 2012-07-04T01:24:11.277 回答