用正则表达式提取单词

far*_*rka 2 regex perl pcre

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

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

为什么?

Axe*_*man 8

您的整个匹配评估为,'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;
Run Code Online (Sandbox Code Playgroud)

'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 );
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

$VAR1 = [
          '1/temperatoA',
          'temperatoA',
          '2/CelcieusB',
          'CelcieusB',
          '23/33',
          '33',
          '55/66',
          '66'
        ];
Run Code Online (Sandbox Code Playgroud)

现在,我认为这可能不是你所期望的.但是'3'并且'6'字符,所以 - 在斜线之后 - 它们符合表达式.

因此,如果这是一个问题,您可以将正则表达式更改为等效的:qr{(\d+/(\p{Alpha}\w*))},指定第一个字符必须是alpha后跟任意数量的单词字符.然后转储看起来像这样:

$VAR1 = [
          '1/temperatoA',
          'temperatoA',
          '2/CelcieusB',
          'CelcieusB'
        ];
Run Code Online (Sandbox Code Playgroud)

如果你只想要'temperatoA'或者'CelcieusB',那么你捕获的数量超过你需要的数量,你就会想要你的正则表达式qr{\d+/(\p{Alpha}\w*)}.

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