giordano
giordano

Reputation: 3162

Perl - grep in foreach does not work with $_ but was with variable

I want to delete some defined elements from a array. I already have a solution with grep and one element: @big = grep { ! /3/ } @big. In case of several elements I want to put them in an array and using foreach. @big is the array from which I want delete elements from @del:

perl -e "@big = (1,2,3,4,5); @del = (2,4); 
      foreach $i (@del) {@big = grep { ! /$i/ } @big; print \"@big\n\"}"

Here is the output:

1 3 4 5
1 3 5

This works fine for me. If I want to use default variable $_ it does not work:

perl -e "@big = (1,2,3,4,5); @del = (2,4); 
      foreach (@del) {@big = grep { ! /$_/ } @big; print \"@big\n\"}"

This gives no output. Any idea what happens?

Upvotes: 1

Views: 419

Answers (1)

aghast
aghast

Reputation: 15310

As @MattJacob points out, there are two conflicting uses for $_:

foreach (@del) {...}

This implicitly uses $_ as the loop variable. From the foreach docs:

The foreach keyword is actually a synonym for the for keyword, so you can use either. If VAR is omitted, $_ is set to each value.

Your grep command also uses $_, always, as part of its processing. So if you had a value in $_ as part of your foreach, and it was replaced in the grep ...?

From the grep docs:

Evaluates the BLOCK or EXPR for each element of LIST (locally setting $_ to each element)

Please do check the grep docs, since there is an explicit warning about modifying a list that you are iterating over. If you are trying to iteratively shrink the list, you might consider some alternative ways to process it. (For example, could you build a single pattern for grep that would combine all the values in your @del list, and just process the @big list one time? This might be quicker, too.)

Upvotes: 3

Related Questions