解析 Perl 范围字符串,例如“1,4..7,10,11”
Parse Perl range string such as "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 在评论中提到的,其他可能的模块是:
当然,最简单和丑陋的解决方案是像这样使用 split
和 eval
:
$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), ")";
您可以通过提取范围内的两个成员来避免 eval
/([0-9]+)[.][.]([0-9]+)/
也可写 /(\d+)\.{2}(\d+)/
:
$str = "1,4..7,10,11";
my @out;
for (split ",", $str) {
if (/(\d+)\.\.(\d+)/) {
push @out, $_ for .. ;
}
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+)/)? .. : $_;
}
print "(", join(',', sort {$a <=> $b} @out), ")";
最后但同样重要的是,如果您使用 bash
并且您的输入字符串作为参数传递给您的程序。您可以像这样使用大括号扩展:
$ echo 1 2 {3..6} 10 11 | sort
1 2 3 4 5 6 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 在评论中提到的,其他可能的模块是:
当然,最简单和丑陋的解决方案是像这样使用 split
和 eval
:
$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), ")";
您可以通过提取范围内的两个成员来避免 eval
/([0-9]+)[.][.]([0-9]+)/
也可写 /(\d+)\.{2}(\d+)/
:
$str = "1,4..7,10,11";
my @out;
for (split ",", $str) {
if (/(\d+)\.\.(\d+)/) {
push @out, $_ for .. ;
}
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+)/)? .. : $_;
}
print "(", join(',', sort {$a <=> $b} @out), ")";
最后但同样重要的是,如果您使用 bash
并且您的输入字符串作为参数传递给您的程序。您可以像这样使用大括号扩展:
$ echo 1 2 {3..6} 10 11 | sort
1 2 3 4 5 6 10 11