Perl正则表达式解析" 1,2,3"到数组

时间:2014-10-02 05:50:50

标签: regex perl split

我希望Perl检查字符串是否包含完全以逗号分隔的数字列表,然后将其拆分为数组。正则表达式/^(\d+)(?:,(\d+))*$/)执行我想要的解析,但是当我在列表上下文中评估它时,我只得到第一个和最后一个数字。我尝试/(?:^|,)(\d+)(?=,|$)/g使 g 修饰符发挥作用以发出多个匹配项,但这无法完全检查语法,如下例所示。那么我如何获得一个完全锚定的正则表达式,就像第一个发送一个多个匹配数组到()*

foreach (@ARGV) {
    #if (my @numbers = /^(\d+)(?:,(\d+))*$/) {
    if (my @numbers = /(?:^|,)(\d+)(?=,|$)/g) {
    print "$_ = (@numbers)\n";
    } else {
    print "$_ isn't a number list!\n";
    }
}

将上述内容放在名为numberlist.pl的文件中并运行它,然后你会得到: -

bash$ perl numberlist.pl 1,2,3 ,1,2,3 1,2,3, a,2,3 1,b,3 1,2,c aa1,2,3zz
1,2,3 = (1 2 3)
,1,2,3 = (1 2 3)
1,2,3, = (1 2 3)
a,2,3 = (2 3)
1,b,3 = (1 3)
1,2,c = (1 2)
aa1,2,3zz = (2)

如果您取消注释第一个if并对第二个进行评论,那么您会得到: -

1,2,3 = (1 3)

因此()(?:)的内容会发出一个匹配项,而不是匹配列表。

我知道我可以使用第一个正则表达式检查语法,然后使用my @numbers = split /,/来获取数组,但是有多种方法可以做到这一点。我只是不太清楚如何。救命啊!

3 个答案:

答案 0 :(得分:0)

/^(?:\d+,)*\d+\z/ or die;
my @numbers = /\d+/g;

my @numbers = split /,/;
die if !@numbers;
for (@numbers) {
   die if !/^\d+\z/;
}

答案 1 :(得分:0)

只需要正则表达式来过滤掉非数字。 split在这里更有用:

for (@ARGV) {
    next unless $_; # Add this to skip processing of blank entries.
    my @l = grep {/^\d+\z/} split /,/;
    print "$_ = (@l)\n";
}

正如所指出的,这会将空字符串视为空列表。这可能是也可能不是你想要的方式。

如果您不介意输入字符串末尾\n的可能性,请将\z更改回模式中的$

答案 2 :(得分:0)

我建议将验证与解析分开:

use strict;
use warnings;

local @ARGV = do {
    no warnings 'qw';
    qw(1,2,3 ,1,2,3 1,2,3, a,2,3 1,b,3 1,2,c aa1,2,3zz);
};

for (@ARGV) {
    if (/^\d+(?:,\d+)*$/) {
        my @numbers = split ',';
        print "Numbers are @numbers\n";
    } else {
        print "NaN = $_\n";
    }
}

输出:

Numbers are 1 2 3
NaN = ,1,2,3
NaN = 1,2,3,
NaN = a,2,3
NaN = 1,b,3
NaN = 1,2,c
NaN = aa1,2,3zz

但是,如果您已加入加入它们,那么请使用正向前瞻断言进行验证,然后像这样进行捕获:

for (@ARGV) {
    if (my @numbers = /\G(?=\d+(?:,\d+)*$)(\d+),?/g) {
        print "Numbers are @numbers\n";
    } else {
        print "NaN = $_\n";
    }
}