在尝试回答this问题时,我遇到了一些来自Perl的正则表达式引擎的奇怪行为。我有一个包含2个数量的字符串,我正在尝试与正则表达式匹配。正则表达式匹配字符串“units / ml”之前的任何8个字符。我想抓住两个单位。
此脚本仅打印匹配的第二个:
use warnings;
use strict;
my $line = 'some data 100,000 units/ml data 20,000 units/ml data';
my @array;
if ($line =~ m/.{8}units\/ml/g) {
@array = $line =~ m/.{8}units\/ml/g;
print join(' ', @array) . "\n";
}
其输出:
20,000 units/ml
如果我两次运行第6行,那么分配给@array的行:
use warnings;
use strict;
my $line = 'some data 100,000 units/ml data 20,000 units/ml data';
my @array;
if ($line =~ m/.{8}units\/ml/g) {
@array = $line =~ m/.{8}units\/ml/g;
# Let's run that again, for good measure...
@array = $line =~ m/.{8}units\/ml/g;
print join(' ', @array) . "\n";
}
其输出:
100,000 units/ml 20,000 units/ml
为什么这两个脚本产生不同的结果?
答案 0 :(得分:3)
这是因为你的if中的/ g修饰符。由于if在标量上下文中评估=〜,因此它只获得匹配的第一个项目。然后,在if块中,@ array指定从中断处继续搜索。 (这对于解析非常有用。)
当你运行额外的匹配时,你已经完成了匹配字符串中的所有内容,所以你从列表上下文中重新开始,然后你得到了所有内容。
如果删除if中的g标志,那么事情就会按预期工作。
答案 1 :(得分:1)
在这种情况下,选项是评估if
语句中的数组赋值:
use Modern::Perl;
my $line = 'some data 100,000 units/ml data 20,000 units/ml data';
my @array;
if ( @array = $line =~ m/.{8}units\/ml/g ) {
print join( ' ', @array ) . "\n";
}
输出:
100,000 units/ml 20,000 units/ml
如果没有匹配,可以采取适当的行动。
答案 2 :(得分:0)
问题出在这里
if ($line =~ m/.{8}units\/ml/g) { ... }
标量上下文中的全局匹配将匹配模式的 next 出现并设置标记以指示下一个全局匹配应从何处开始
之后只剩下20,000 units/ml
个匹配模式,因此只匹配一次
要收集字符串后跟units/ml
的所有数字或逗号,您应该写下这样的内容
use strict;
use warnings;
my $line = 'some data 100,000 units/ml data 20,000 units/ml data';
my @array = $line =~ m|([0-9,]+)\s*units/ml|g;
print "$_\n" for @array;
<强>输出强>
100,000
20,000