如何在<stdin>的输入上应用perl范围运算符?

时间:2017-03-08 05:51:28

标签: perl

我无法对从标准输入获取的输入应用perl范围运算符。这是代码:

#!/usr/bin/perl
@range = (1..5, 6, 7, 8..10);
print "@range\n";

print "Enter your range. Esc by CTRL+D.\n";
chomp(@user_range = <STDIN>); # input 1..5<LF> 6<LF> 7..10<LF> CTRL+D
print "@user_range\n";

第一个代码块(@range)工作正常输出:1 2 3 4 5 6 7 8 9 10; 秒(@user_range)输入1..5 6 7..10 CTRL + D 。我得到的输出是1..5 6 7..10 而不是1 2 3 4 5 6 7 8 9 10.

请帮忙。

1 个答案:

答案 0 :(得分:4)

您从STDIN或任何其他文件句柄中读取的任何内容都只是一个字符串。这是一项基本的安全措施,您不希望您的编程语言将输入评估为代码。

你可以通过eval运行它,但那是一个安全漏洞;它允许用户运行任意代码。 不要使用eval STRING ,除非您知道自己在做什么。 eval BLOCK很好,它完全不同。

相反,如果你想要做一些事情来输入你,你必须自己做。如果它只是简单的数字,那么它可以相当简单。

use 5.010;
use strict;
use warnings;

# Read the string from input and remove the newline.
my $list_string = <STDIN>;
chomp $list_string;

# Split it into a list on commas.
# "1..5, 6, 7..10" becomes "1..5", "6", "7..10".
my @list = split /\s*,\s*/, $list_string;

# Go through each element checking for a range operator.
# If there's a range operator, replace it with the range.
# Otherwise leave it alone.
@list = map { range_transform($_) } @list;

print join ", ", @list;

sub range_transform {
    my $string = shift;

    # Match the X..Y. If it doesn't match, just return it.
    return $string unless $string =~ m{^(\d+)\.\.(\d+)$};

    # Perform the range operation.
    return $1..$2;   
}

这没有任何错误检查,它也应该检查输入是一个数字还是一个范围操作符,如果它是其他任何东西就呕吐。但这应该让你开始。