6

我有一个 Perl 应用程序,它从命令行获取输入:

application --fields 1-6,8

我需要在命令行上显示用户请求的字段。

我想用'..'代替'-',这样我就可以将它们存储在数组中,例如

$str = "1..15,16" ;
@arr2 = ( $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;

这里的问题是@arr 可以正常工作(应该如此),但在@arr2 中,整个字符串不会扩展为数组元素。

我尝试过使用转义序列,但没有运气。

可以这样做吗?

4

6 回答 6

26

如果这是用户输入,如果您有任何安全问题,请不要在其上使用字符串 eval。

尝试使用Number::Range代替:

 use Number::Range;

 $str = "1..15,16" ;
 @arr2 = Number::Range->new( $str )->range;
 print for @arr2;

为避免在无效范围内死亡,请执行以下操作:

 eval { @arr2 = Number::Range->new( $str )->range; 1 } or your_error_handling

还有Set::IntSpan,它使用 - 而不是 ..:

 use Set::IntSpan;

 $str = "1-15,16";
 @arr2 = Set::IntSpan->new( $str )->elements;

但它要求范围是有序且不重叠的(它是为 .newsrc 文件而编写的,如果有人记得那些是什么的话)。它还允许无限范围(字符串开始的地方 -数字或结束数字- ),元素方法将在这些范围内发牢骚。

于 2009-06-19T08:13:41.007 回答
1

您正在考虑@arr2 = eval($str); 由于您正在接受输入并对其进行评估,因此您需要小心。你应该可能@arr2 = eval($str) if ($str =~ m/^[0-9.,]+$/)

PS 我不知道 Number::Range 包,但它很棒。编号::范围 ftw。

于 2009-06-19T07:46:00.940 回答
1

在处理 Bit::Vector::to_Enum 的输出时,我遇到了同样的问题。我通过这样做解决了它:

$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;

然后也在我的文件中:

sub expand_range
{
    return join(",",($_[0] .. $_[1]));
}

所以“1,3,5-7,9,12-15”变成了“1,3,5,6,7,9,12,13,14,15”。

我非常努力地将扩展放在 s/// 的第二部分,所以我不需要那个额外的功能,但我无法让它工作。我喜欢这个,因为虽然 Number::Range 可以工作,但这样我就不必为应该微不足道的事情引入另一个模块。

于 2011-12-21T01:15:42.670 回答
0
@arr2 = ( eval $str ) ;

工作,当然你必须非常小心 eval()。

于 2009-06-19T07:37:57.540 回答
0

你可以使用评估:

$str = "1..15,16" ;
@arr2 = ( eval $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;

虽然如果这是用户输入,您可能需要先对输入字符串进行一些验证,以确保他们没有输入任何不可靠的内容。

于 2009-06-19T07:39:17.787 回答
-2

使用拆分:

@parts = split(/\,/, $fields);

print $parts[0];
1-6
print $parts[1];
8

你不能只把一个包含 ',' 的字符串放在一个数组中,然后期望它变成元素(除非你使用一些 Perl 黑魔法,但我们不会在这里讨论)

但是 Regex 和 split 是你的朋友。

于 2009-06-19T07:35:05.533 回答