views:

248

answers:

5

I have a Perl application that takes from command line an input as:

application --fields 1-6,8

I am required to display the fields as requested by the user on command line.

I thought of substituting '-' with '..' so that I can store them in array e.g.

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

The problem here is that @arr works fine ( as it should ) but in @arr2 the entire string is not expanded as array elements.

I have tried using escape sequences but no luck.

Can it be done this way?

A: 

Use split:

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

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

You can't just put a string containing ',' in an array, and expect it to turn to elements (except if you use some Perl black magic, but we won't go into that here)

But Regex and split are your friends.

Chaos
that i understand... <br/>actually what i want is finally the @parts should contain ( 1,2,3,4,5,6,8 )<br/>which is equivalent to ( 1..6,8 )
Neeraj
A: 
@arr2 = ( eval $str ) ;

Works, though of course you have to be very careful with eval().

Jonathan Maddison
thanx ... i needed just that
Neeraj
A: 

You could use eval:

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

Although if this is user input, you'll probably want to do some validation on the input string first, to make sure they haven't input anything dodgy.

Tom
+1  A: 

You're thinking of @arr2 = eval($str); Since you're taking input and evaluating that, you need to be careful. You should probably @arr2 = eval($str) if ($str =~ m/^[0-9.,]+$/)

P.S. I didn't know about the Number::Range package, but it's awesome. Number::Range ftw.

dlamblin
+21  A: 

If this is user input, don't use string eval on it if you have any security concerns at all.

Try using Number::Range instead:

 use Number::Range;

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

To avoid dying on an invalid range, do:

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

There's also Set::IntSpan, which uses - instead of ..:

 use Set::IntSpan;

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

but it requires the ranges to be in order and non-overlapping (it was written for use on .newsrc files, if anyone remembers what those are). It also allows infinite ranges (where the string starts -number or ends number-), which the elements method will croak on.

ysth
+1. "Doing it right" is always preferable to eval. Many fewer side effects.
jrockway
I've never come across Number::Range before. I've filed that away for future use. Thanks for making me aware of it!
Nic Gibson
If you take user input, your app will blow up on 1..1000000000, unless you have about 8GB of RAM. Number::Range->size() is useless right now to prevent this as it generates the whole range to figure out the size.
Mathieu Longtin
@Mathieu Longtin: the question implies these are are indexes of some other, already in memory, data. so there isn't going to be any such range.
ysth
That's why you always do a sanity check on user input before using it.
Lars Haugseth