On 04/03/2012 07:56, Manfred Lotz wrote:
Hi there,
I've got a strange problem with $_. It seems I do not understand
something which might be basic. Anyway, here is a minimal example.

#! /usr/bin/perl

use strict;
use warnings;
use 5.010;

sub sub1 {
   my $cmd = shift;

   print "Sub3: Issuing [$cmd]\n";
   open my $fh, '-|', "$cmd 2>&1" or die "open: $!";
   while (<$fh>  ) { print; }
   close $fh;
   return $?>>  8;
}

sub sub2 {
   my $cmd = shift;

   say "\nSub1 $cmd";
   return 1;
}


my @cmds = ( "uname -a", "date");

foreach ( @cmds ) { say sub1($_); };
foreach ( @cmds ) { say sub2($_); };

Running this gives:

Sub3: Issuing [uname -a]
Linux hogwart 3.0.0-14-generic-pae #23~lucid1-Ubuntu SMP Thu Dec 8
15:03:12 UTC 2011 i686 GNU/Linux 0
Sub3: Issuing [date]
Sun Mar  4 08:54:18 CET 2012
0
Use of uninitialized value $cmd in concatenation (.) or string
at ./foreach1.pl line 20.

Sub1
1
Use of uninitialized value $cmd in concatenation (.) or string
at ./foreach1.pl line 20.

Sub1
1


What am I doing wrong here?

Hi Manfred

You have discovered why many people say it is unsafe to use $_. $_ is a
global variable, and the loop

  while (<$fh>  ) { print; }

modifies it, leaving it undefined at end of file. Unfortunately the loop

  foreach ( @cmds ) { say sub1($_); };

has aliased $_ to each of the elements of @cmds, so the array is getting
corrupted by the subroutine call.

You can get around this either by using a named variable for reading
from the pipe, or by adding

  local $_;

at the start of sub1 in anticipation of changing its value, so that the
copy that the main program is using doesn't get corrupted.

Cheers,

Rob

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to