Regex 为什么两次运行同一个正则表达式会产生不同的结果?
在试图回答这个问题时,我遇到了一些来自Perl的正则表达式引擎的奇怪行为。我有一个字符串,其中包含两个数量,我试图与正则表达式匹配。正则表达式只匹配字符串“units/ml”之前的任意8个字符。我想抓住两个单位 此脚本仅打印匹配的第二个脚本:Regex 为什么两次运行同一个正则表达式会产生不同的结果?,regex,perl,Regex,Perl,在试图回答这个问题时,我遇到了一些来自Perl的正则表达式引擎的奇怪行为。我有一个字符串,其中包含两个数量,我试图与正则表达式匹配。正则表达式只匹配字符串“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
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
100,000 units/ml 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";
}
其产出:
20,000 units/ml
100,000 units/ml 20,000 units/ml
为什么这两个脚本会产生不同的结果?这是因为if中的/g修饰符。由于if在标量上下文中计算=~值,因此它只获得匹配的第一个项。然后,在if块内,@array赋值从它停止的位置继续搜索。(这对于解析非常有用。) 当您运行额外的匹配时,您已经完成了对字符串中所有内容的匹配,因此您可以在列表上下文中从头开始,然后获得所有内容
如果您删除If中的g标志,那么事情就会按照您的预期进行。这是因为If中的/g修饰符。由于if在标量上下文中计算=~值,因此它只获得匹配的第一个项。然后,在if块内,@array赋值从它停止的位置继续搜索。(这对于解析非常有用。) 当您运行额外的匹配时,您已经完成了对字符串中所有内容的匹配,因此您可以在列表上下文中从头开始,然后获得所有内容
如果删除If中的g标志,则一切正常。在本例中,一个选项是在
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
如果需要,如果没有匹配,可以采取适当的措施。在这种情况下,一个选项是在
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
如果需要,如果没有匹配,可以采取适当的措施。问题就在这里
if ($line =~ m/.{8}units\/ml/g) { ... }
标量上下文中的全局匹配将匹配模式的下一个匹配项,并设置一个标记来说明下一个全局匹配的开始位置
在此之后,只剩下与模式匹配的20000单位/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
问题就在这里
if ($line =~ m/.{8}units\/ml/g) { ... }
标量上下文中的全局匹配将匹配模式的下一个匹配项,并设置一个标记来说明下一个全局匹配的开始位置
在此之后,只剩下与模式匹配的20000单位/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
是的,这和我想做的差不多。但是,您可以将my放入if语句中:
if(my@array=…){@array valid here}但不在这里
@Tanktalus-确实可以,提到这一点很好+1是的,这与我会做的非常接近。但是,您可以将my放入if语句中:if(my@array=…){@array valid here}但不在这里
@Tanktalus-确实可以,提到这一点很好+1.