解析 Perl 范围字符串,例如 "1,4..7,10,11"



给定一个字符串,如1,4..7,10,11,有没有一种巧妙的方法将其解析到列表(1,4,5,6,7,10,11)中?该字符串作为命令行参数提供。我的计划是确保字符串适合/^[0-9.,]+$/,然后适合eval,但没有eval有更整洁的方法吗?

查看CPAN模块Text::NumericList。

将字符串转换为数组:

use Text::NumericList;
my $list = Text::NumericList->new;
$list->set_string('1-3,5-7');
my @array = $list->get_array;     # Returns (1,2,3,5,6,7)

$list->set_string('1..3,5...7');
@array = $list->get_array;        # Returns (1,2,3,5,6,7)

正如@dgw在评论中提到的,其他可能的模块有:

编号::范围
设置::Intspan

当然,最简单而丑陋的解决方案是像这样使用spliteval

$str = "1,4..7,10,11";
my @out;
for (split ",", $str) {
    if (/d+..d+/) {
        eval('push @out, $_ for '.$_);
    }
    else {
        push @out, $_;
    }
}
print "(", join(',', sort {$a <=> $b} @out), ")"; 

您可以通过使用/([0-9]+)[.][.]([0-9]+)/(也可写/(d+).{2}(d+)/:(提取范围的两个成员来避免eval

$str = "1,4..7,10,11";
my @out;
for (split ",", $str) {
    if (/(d+)..(d+)/) {
        push @out, $_ for $1 .. $2;
    }
    else {
        push @out, $_;
    }
}
print "(", join(',', sort {$a <=> $b} @out), ")"; 

由此我们可以简化代码:

$str = "1,4..7,10,11";
my @out;
for (split ",", $str) {
    push @out, $_ for (/(d+)..(d+)/)? $1 .. $2: $_; 
}
print "(", join(',', sort {$a <=> $b} @out), ")"; 

最后但同样重要的是,如果您使用bash,并且您的输入字符串作为参数传递给程序。你可以这样使用支架扩展:

$ echo 1 2 {3..6} 10 11 | sort
1 2 3 4 5 6 10 11

最新更新