一个简短的问题:我希望为我的脚本用户提供输入任意数组的可能性,例如: "[1 .. 5]"
或"[1, 2, 6, 9 .. 20]"
。目前,我只是eval
给定的字符串(显然不是很安全!)而perlcritic
给了我5级警告。
我目前的代码:
my $arr = eval $patternData{"arr"};
unless ($arr) {
# fixes <arr> values like "(1 .. 5)"
$arr = undef;
@$arr = eval $patternData{"arr"};
}
编辑:很多人都在问:这是一个“越多越好”的东西。我搜索一个既强大(在表达方面)又简单(在调试,解析和写入输入方面)的解决方案。另外:它必须支持范围(应该容易输入超过100个条目的数组)
和 - 一如既往 - 我忘了包含我的版本。 5.8是必须的,我正在使用vSphere API,这需要5.8(我非常想念~~
!)
This is perl, v5.8.8 built for MSWin32-x86-multi-thread
(with 50 registered patches, see perl -V for more detail)
Copyright 1987-2006, Larry Wall
Binary build 820 [274739] provided by ActiveState http://www.ActiveState.com
Built Jan 23 2007 15:57:46
答案 0 :(得分:4)
您对当前的输入格式有多大关系?
一个问题可能是将格式“更改”为JSON并使用JSON :: XS反序列化您的输入。 [1, 2, 3, 4]
仍然是有效输入,但这不允许[1, 2, 3, 4, 8 .. 10 ]
在所有情况下,您当然需要验证输入数据是否具有正确的结构。
答案 1 :(得分:2)
如果您的数组只允许数字,我会选择这种模式(易于解析):
[1, 2, 3, 4]
我进一步假设不会有嵌套数组,例如[1, [2, 3]]
或尾随逗号[1,]
。
然后我们只删除数组分隔符
my $line = <STDIN>;
$line =~ s/ ^\s*\[ | \]\s*$ //gx;
并将数组拆分为Perl数组。我们可以通过split
my @array = split /,\s*/, $line;
或通过提取所有数字
my @array = ($line =~ /(\d+)(?:,\s*|$)/g);
split
解决方案还允许包含字符串,例如[1, two, 3]
,而第二种解决方案更严格(因此可能更安全)。
在第二步中,您可以解析范围,例如通过
@array = map {
($_ =~ /^(-?[\d.]+)\s*\.\.\s*(-?[\d.]+)/)
? ($1 .. $2)
: $_
} @array;
如果您的数据结构变得更复杂(递归,引用),我强烈建议您使用Regexp::Grammars编写解析器。这使您可以轻松地解析递归结构以及几乎任何其他结构。