Vinay
Vinay

Reputation: 477

How can I grep in a Perl loop?

I am trying to grep in Perl using the following code:

my @S = grep /M1A3B6/, @AR3; 
print @S;

However, grep through loop did not return any value.

for(my $j=0; $j<$ln1; $j++){
    @S = grep /$AR1[$j]/, @AR3;
    $j++;
}
print @S;

The sample files are as follows:

@AR1
M1A3B6
M1AZ83

@AR3
>tr|M1A3B6|Uncharacterized protein >>MFNLHLLAVG
>tr|M1AP92|Uncharacterized protein >>MQTLSRAQSQ
>tr|M1AZ83|Uncharacterized protein >>MASFTTLTSLFFFF

All suggestions will be appreciated.

Upvotes: 1

Views: 976

Answers (3)

BOC
BOC

Reputation: 1139

I agree with Dave Sherohman, but I wanted to highlight a more concise syntax:

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

my @ar1 = qw( M1A3B6 M1AZ83 );
my @ar3 = (
  '>tr|M1A3B6|Uncharacterized protein >>MFNLHLLAVG',
  '>tr|M1AP92|Uncharacterized protein >>MQTLSRAQSQ',
  '>tr|M1AZ83|Uncharacterized protein >>MASFTTLTSLFFFF'
);

my @s = map {my $key = $_;grep /$key/, @ar3} @ar1;

say for @s;

This uses the fact that the block part of map is evaluated in list context and may produce zero, one, or more elements in the returned value. This combine very nicely with grep when we want to concatenate all the outputs.

Upvotes: 1

mkHun
mkHun

Reputation: 5927

Try something like below as mentioned, Join the array using | then grep it.

my @ar1 = qw(M1A3B6 M1AZ83);
my @ar3 = (
  '>tr|M1A3B6|Uncharacterized protein >>MFNLHLLAVG',
  '>tr|M1AP92|Uncharacterized protein >>MQTLSRAQSQ',
  '>tr|M1AZ83|Uncharacterized protein >>MASFTTLTSLFFFF'
);

my $pattern = join("|",@ar1);
my @data = grep{ /$pattern/ } @ar3;
print "@data\n";

Upvotes: 0

Dave Sherohman
Dave Sherohman

Reputation: 46187

There are a couple significant problems in the structure of your posted code:

  1. You're incrementing $j twice in each iteration (once with the $j++ in the for statement itself, then another $j++ in the body of the loop). This will cause it to skip over every other element in @AR1. Because it's so easy to make errors like this with C-style loops, it's generally better to use for (@list) instead of the C-style for (;;) when you're just iterating over a list of items.
  2. You're assigning directly to @S on each iteration of the loop, which replaces any existing content with the new grep result. This means that, at the end of the loop, @S contains only the results found in the final iteration instead of all the results found throughout the process. You need to append to @S instead.
  3. ALWAYS use strict; and use warnings;. Yes, it can be a minor hassle to get used to them and satisfying their demands, but they are your best friends when it comes time for debugging.

Here's how I would do what your posted code appears to intend:

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

my @ar1 = qw( M1A3B6 M1AZ83 );
my @ar3 = (
  '>tr|M1A3B6|Uncharacterized protein >>MFNLHLLAVG',
  '>tr|M1AP92|Uncharacterized protein >>MQTLSRAQSQ',
  '>tr|M1AZ83|Uncharacterized protein >>MASFTTLTSLFFFF'
);

my @s;
for my $key (@ar1) {
  push @s, (grep /$key/, @ar3);
} 

say for @s;

And the resulting output:

>tr|M1A3B6|Uncharacterized protein >>MFNLHLLAVG
>tr|M1AZ83|Uncharacterized protein >>MASFTTLTSLFFFF

Upvotes: 7

Related Questions