eyepopslikeamosquito has asked for the wisdom of the Perl Monks concerning the following question:
I have a table of commands to run and want to provide a convenient command line user interface to allow the user to select which (zero-based) indices from the table (implemented as a Perl array) to run.
Assuming a command table of eleven commands, say (index 0..10) you might try:
This covers the common case of running a range of contiguous commands. Suggestions for a nice command line user interface welcome.somecommand 4 # run index 4 from the command table somecommand 4-6 # run indices 4,5,6 from the command table somecommand 5- # run indices 5,6,7,8,9,10 from the command table somecommand -2 # run indices 0,1,2 from the command table
Given the user interface described above, I wrote a function to convert from the user interface "range string" to a list suitable for use in a Perl array slice.
To clarify the spec, note that running the test program rl.pl above produces:use strict; use warnings; # This function takes a "range string" and returns # a list that can be used in a Perl array slice. # Some examples should clarify: # Range string Return list # "4" (4) # "4-6" (4,5,6) # "5-" (5,6,7,...,$maxind) # "-2" (0,1,2) sub range_to_list { my $maxind = shift; # max index of (zero-based) list my $range = shift; # a "range string" (see examples above) my @ilist = split /-/, $range, 2; my $nlist = @ilist; $nlist == 1 || $nlist == 2 or die "range_to_list $nlist out of rang +e"; if ( $nlist == 1 ) { $ilist[0] =~ /^\d+$/ or die "range_to_list, '$ilist[0]' not nume +ric"; $ilist[0] <= $maxind or die "range_to_list, '$ilist[0]' out of r +ange"; return @ilist; } if ( $ilist[0] eq '' ) # e.g. "-5" case { $ilist[1] =~ /^\d+$/ or die "range_to_list, '$ilist[1]' not nume +ric"; $ilist[1] <= $maxind or die "range_to_list, '$ilist[1]' out of r +ange"; return ( 0 .. $ilist[1] ); } if ( $ilist[1] eq '' ) # e.g. "3-" case { $ilist[0] =~ /^\d+$/ or die "range_to_list, '$ilist[0]' not nume +ric"; $ilist[0] <= $maxind or die "range_to_list, '$ilist[0]' out of r +ange"; return ( $ilist[0] .. $maxind ); } # e.g. "3-5" case $ilist[0] =~ /^\d+$/ or die "range_to_list, '$ilist[0]' not numeric +"; $ilist[1] =~ /^\d+$/ or die "range_to_list, '$ilist[1]' not numeric +"; return ( $ilist[0] .. $ilist[1] ); } my $maxind = 10; print "maxind=$maxind\n"; for my $rstr ( "x", "1-2-3", "0", "10", "11", "4", "4-6", "7-", "-2", "-10", "-11", "-0", "10-", "11-" ) { print "rstr:$rstr:"; my @ret; eval { @ret = range_to_list( $maxind, $rstr ) }; if ($@) { print "...exc:$@"; } else { print "...ret:@ret:\n"; } } my @apples = ( ":zero:", ":one:", ":two:", ":three:", ":four:" ); print "apples ", @apples[range_to_list( $#apples, "1-3" )], "\n";
Implementation improvements of this inelegant first attempt welcome.maxind=10 rstr:x:...exc:range_to_list, 'x' not numeric at rl.pl line 21. rstr:1-2-3:...exc:range_to_list, '2-3' not numeric at rl.pl line 39. rstr:0:...ret:0: rstr:10:...ret:10: rstr:11:...exc:range_to_list, '11' out of range at rl.pl line 22. rstr:4:...ret:4: rstr:4-6:...ret:4 5 6: rstr:7-:...ret:7 8 9 10: rstr:-2:...ret:0 1 2: rstr:-10:...ret:0 1 2 3 4 5 6 7 8 9 10: rstr:-11:...exc:range_to_list, '11' out of range at rl.pl line 28. rstr:-0:...ret:0: rstr:10-:...ret:10: rstr:11-:...exc:range_to_list, '11' out of range at rl.pl line 34. apples :one::two::three:
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Specifying a range of indices via the command line
by AnomalousMonk (Archbishop) on Feb 15, 2015 at 07:20 UTC | |
|
Re: Specifying a range of indices via the command line
by BrowserUk (Patriarch) on Feb 15, 2015 at 12:24 UTC | |
|
Re: Specifying a range of indices via the command line
by hdb (Monsignor) on Feb 15, 2015 at 08:34 UTC | |
|
Re: Specifying a range of indices via the command line
by kroach (Pilgrim) on Feb 15, 2015 at 11:58 UTC | |
|
Re: Specifying a range of indices via the command line
by BrowserUk (Patriarch) on Feb 15, 2015 at 14:02 UTC |