我有一个字符串1/temperatoA,2/CelcieusB!23/33/44,55/66/77,我想提取单词temperatoA和CelcieusB.
我有这个正则表达式,(\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;
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*)}.
但是,捕获表达式中捕获多个块的秘诀是将匹配分配给数组,然后可以对数组进行排序以查看它是否包含所需的数据.