circuit.maker
circuit.maker

Reputation: 31

How to apply perl range operator on input from <STDIN>?

I'm not able to apply perl range operator over an input taken from Standard Input. Here's the code:

#!/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";

The first block of code (@range) works fine and outputs: 1 2 3 4 5 6 7 8 9 10; In the second (@user_range) I input 1..5 6 7..10 CTRL+D. The output I get is 1..5 6 7..10 instead of 1 2 3 4 5 6 7 8 9 10.

Please help.

Upvotes: 1

Views: 262

Answers (1)

Schwern
Schwern

Reputation: 164909

Anything you read from STDIN or any other filehandle comes in as just a string. This is a basic security measure, you don't want your programming language evaluating input as code.

You could run it through eval, but that's a security hole; it lets users run arbitrary code. Don't use eval STRING unless you know what you're doing. eval BLOCK is fine, it's totally different.

Instead, if you want something done to input you'll have to do it yourself. If it's just simple numbers, then it can be fairly straightforward.

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;   
}

This doesn't have any error checking, it should probably also check that the input is either a number OR a range operator and puke if it's anything else. But that should get you started.

Upvotes: 4

Related Questions