我有一个字符串1/temperatoA,2/CelcieusB!23/33/44,55/66/77,我想提取单词temperatoACelcieusB

我有这个正则表达式(\d+/(\w+),?)*!,但是我只得到匹配的1/temperatoA,2/CelcieusB!
为什么?

最佳答案

您的整个匹配结果为'1/temperatoA,2/CelcieusB',因为它与以下表达式匹配:

qr{ (       # begin group
      \d+   # at least one digit
      /     # followed by a slash
     (\w+)  # followed by at least one word characters
     ,?     # maybe a comma
    )*      # ANY number of repetitions of this pattern.
}x;
'1/temperatoA,'首先实现捕获#1,但是由于您要求引擎捕获尽可能多的捕获,因此它会返回并发现'2/CelcieusB'中重复了该模式(不需要逗号)。所以整个比赛就是您所说的,但您可能没想到的是'2/CelcieusB''1/temperatoA,'替换为 $1 ,因此$1读取'2/CelcieusB'

每当您要捕获适合特定模式的特定字符串时,总是最好使用 g lobal标志并将捕获分配到数组中。由于数组不是像$1这样的单个标量,因此它可以保存为捕获#1捕获的所有值。

当我这样做时:
my $str   = '1/temperatoA,2/CelcieusB!23/33/44,55/66/77';
my $regex = qr{(\d+/(\w+))};
if ( my @matches = $str =~ /$regex/g ) {
    print Dumper( \@matches );
}

我得到这个:
$VAR1 = [
          '1/temperatoA',
          'temperatoA',
          '2/CelcieusB',
          'CelcieusB',
          '23/33',
          '33',
          '55/66',
          '66'
        ];

现在,我认为这可能不是您所期望的。但是'3''6'是单词字符,因此-在斜杠后面出现-它们符合表达式。

因此,如果这是一个问题,则可以将正则表达式更改为等效项:qr{(\d+/(\p{Alpha}\w*))},指定第一个字符必须为字母,后跟任意数量的单词字符。然后转储如下所示:
$VAR1 = [
          '1/temperatoA',
          'temperatoA',
          '2/CelcieusB',
          'CelcieusB'
        ];

而且,如果只希望'temperatoA''CelcieusB',那么您捕获的内容将超出您的需要,并且您希望正则表达式为qr{\d+/(\p{Alpha}\w*)}

但是,在捕获表达式中捕获多个块的 secret 是将匹配项分配给数组,然后可以对数组进行排序以查看其是否包含所需的数据。

09-25 22:06