3

I'm in the process of learning Perl and am trying to write a script that takes a pattern and list of files as command line arguments and passes them to a subroutine, the subroutine then opens each file and prints the lines that match the pattern. The code below works; however, it stops after printing the lines from the first file and doesn't even touch the second file. What am I missing here?

#!/usr/bin/perl
use strict;
use warnings;

 sub grep_file 
 {
  my $pattern = shift;
  my @files = shift;

  foreach my $doc (@files) 
  {
    open FILE, $doc;
    while (my $line = <FILE>) 
    {
      if ($line =~ m/$pattern/) 
      {
        print $line;
      }
    }
  }

grep_file @ARGV;
0

2 Answers 2

8

Shift pops an element from your parameter (see: http://perldoc.perl.org/functions/shift.html).

So @files can only contain one value.

Try

sub foo
{
 my $one = shift @_;
 my @files = @_;
 print $one."\n";
 print @files;
}

foo(@ARGV);
Sign up to request clarification or add additional context in comments.

4 Comments

Of course! I had a similar but different understanding of shift. Thanks a lot, it worked.
Borodin: You are right, so I removed the information that he may feel to accept this as answer if it helped him (as he had shown). Regarding his point stats I just wanted to show him that if this helped like he explained he can accept this answer to set the problem as solved.
I think that, after a day or so, it is fine to post a comment under the question to explain that an answer should be accepted if the problem has been resolved.
What I mean is that your foo is very unlike the OP's grep_file, and it prints file1file2file3file4file5file6 on a line after the regex.
1

There is little reason to use a subroutine here. You are just putting the whole program inside a function and then calling it.

The empty <> operator will read from all the files in @ARGV in sequence, without you having to open them explicitly.

I would code your program like this

use strict;
use warnings;

my $pattern = shift;
$pattern = qr/$pattern/; # Compile the regex

while (<>) {
  print if $_ =~ $pattern;
}

4 Comments

I agree by not needing a subroutine, but maybe he just built a simple example to understand his problem and solve it.
Perhaps. But your own answer explains why the OP is getting unexpected results (with an oddly-irrelevant subroutine!)
I can't understand why a simple and minimalistic example demonstrating the way shift works is oddly-irrelevant? In such a case, your answer should be discarded the same way. Just leaving a reference to the perl shift documentation uncommented must then be the only correct answer.
@Stefan This is about your own answer so I have responded there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.