当然,最简单和丑陋的解决方案是像这样使用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), ")";
您可以通过使用/([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