我有一个文件,其中包含使用以下语法的参数
RANGE {<value> | <value>-<value>} [ , ...]其中value s是数字。
例如,所有这些都是有效的语法。
RANGE 34
RANGE 45, 234
RANGE 2-99
RANGE 3-7, 15, 16, 2, 54如何将值解析为Perl中的数组?
例如,对于最后一个示例,我希望我的数组具有3, 4, 5, 6, 7, 15, 16, 2, 54。元素的排序并不重要。
最基本的方法是检查-符号以确定是否存在范围,使用循环解析范围,然后解析其余的元素。
my @arr;
my $fh, "<", "file.txt" or die (...);
while (<$fh>) {
if ($_ =~ /RANGE/) {
if ($_ =~ /-/) { # parse the range
< how do I parse the lower and upper limits? >
for($lower..$upper) {
$arr[++$#arr] = $_;
}
} else { # parse the first value
< how do I parse the first value? >
}
# parse the rest of the values after the comma
< how do I parse the values after the comma? >
}
}-、,和)上。是否有更好的(干净和优雅,使用正则表达式?)方法?发布于 2010-09-21 19:58:44
我建议将行解析为一个单独的变量,因为$_往往会受到其他函数调用的打击。您可以同时使用chomp删除尾随换行符。
while (<$fh)>
{
chomp (my $line = $_);
# ...
}接下来,您需要检测“范围”指示器,并提取后面的数字。如果没有这样的指示符,可以跳到下一行:
next if $line !~ /^RANGE (.*)$/;现在,您可以开始提取数字,在逗号分隔符上拆分:
my @ranges = split /, /, $1;现在,您可以提取破折号并将其转换为范围。这是一个棘手的部分--如果值中有一个破折号,那么获取第一个和第二个数字,然后用..操作符将它们转换成一个范围;否则,不要使用这个数字:
@ranges = map { /(\d+)-(\d+)/ ? ($1 .. $2) : $_ } @ranges;把所有这些结合在一起,并结合表达,让我们:
my @numbers;
while (<$fh)>
{
chomp (my $line = $_);
next if $line !~ /^RANGE (.*)$/;
push @numbers, map { /(\d+)-(\d+)/ ? ($1 .. $2) : $_ } (split /, /, $1);
}发布于 2010-09-21 19:51:09
查看一下来自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)您至少可以查看它的源代码以获得想法。
发布于 2010-09-21 19:55:50
那这个呢?
首先将行拆分为由值分隔的元素,然后检查是否有“-”符号来创建范围:
if ($line =~ /RANGE ([\d\,\- ]+)/) {
my $paramtxt = $1;
my @elements = split(/\,/, $paramtxt);
for my $element (@elements) {
if ($element =~ /(\d+)\-(\d+)/) {
$lower = $1;
$upper = $2;
push @arr, $lower .. $upper;
} elsif ($element =~ /(\d+)/) {
$solo = $1;
push @arr, $solo;
}
}
}https://stackoverflow.com/questions/3763843
复制相似问题