On Tue, 19 Jun 2001 15:25:56 +0200, Bart Lateur wrote:
>On Tue, 19 Jun 2001 03:09:54 +0200 (MEST), Louis Pouzin wrote:

>>I want to test and remove one element of an array when it is '-s'.
>>
>>The following script works, with a diag: Use of uninitialized value, in line 5. It 
>seems related to '-s'.
>>
>>      #!/usr/local/bin/perl -w
>>      @ARGV = (2, '-s', 'fil');
>>      my $sel = 0;
>>      for (0..$#ARGV) {
>>              $ARGV[$_] =~ /^-s$/o || next;
>>              $sel = 1; splice(@ARGV,$_,1);
>>      }
>>      print "$sel, @ARGV \n";
>>      __END__
>>
>>If I replace -s by -\s or -\\s, the diag disappears, but the regex fails. What is a 
>right way to do it ?

>The reason is that, when you do that, your @ARGV gets smaller. So you're testing 
>beyond the end of the array.

Does this mean that the "for" boundaries are evaluated only on the 1st loop ?  Then 
$#ARGV doesn't reflect the array variations.

>Plus: you're skipping a file. You're testing items 0, 1 and 2, but if 1 is dropped, 
>then 2 becomes 1, and you don't test it.

That's right.

>Some solutions:

> * Do it with a C style for loop (or a while loop), and increment only if there was 
>no splice.

>       for(my $i = 0; $i < @ARGV; ) {
>           if($ARGV[$i] eq '-s') {
>               splice @ARGV, $i, 1;
>           } else {
>               $i++;
>           }
>       }

>Very messy, if you ask me.

It works, with the addition of $sel=1 after splice.

> * Go backwards through the array.

>       for(reverse 0 .. $#ARGV) {
>           if($ARGV[$_] eq '-s') {
>               splice @ARGV, $_, 1;
>           }
>       }

>Better.

It works. Same addition as above.

> * But my favourite is to use grep():

>       @ARGV = grep { $_ ne '-s' } @ARGV;

>Caveat: all untested. How unresponsible. And you have to put the test for whether 
>'-s' was there, in it somewhere.

It's great. Here is the complete script: 

        #!/usr/local/bin/perl -w
        @ARGV = (2,'-s','fil'); my $sel = 0;
        grep { /^-s$/o && ($sel = 1) } @ARGV;
        @ARGV = grep { $_ ne '-s' } @ARGV;
        print "$sel, @ARGV \n";
        __END__

Could the 2 grep's be somehow merged ?

Thanks Bart. You taught me new tricks. I'm still in the lower learning curve.
=====

Reply via email to