[comp.lang.perl] Problem with -i option and <> in array context

gson@blob.hut.fi (Andreas Gustafsson) (05/11/91)

I am trying to munge some mailbox files in-place by using Perl with
the -i option.  The file is accessed in a somewhat random fashion, so
I want to read the whole file into an array using @array=<>.  It turns
out that this doesn't work very well with the -i option.  Consider the
following program:

#!/p/bin/perl -i.bak
@lines=<>;
for(@lines)
{ s/^/X /;
}
$;="\n";
print @lines;

When running the above program with a text file "foo" as an argument,
it correctly prepends "X " to each line in the file but instead of
modifying the file in-place it prints the modified file on standard
output, leaving an em does work as expected:
The following program, which does not use <> in an array context,

#!/p/bin/perl -i.bak
while(<>)
{ s/^/X /;
  print;
}

Versions 3.0pl37 and 4.003 both behave this way.  The man page says
that with -i, "files processed by the <> construct are to be edited
in-place", not "files processed by the _scalar_ <> construct ...".  Is
this a bug in Perl, a bug in the man page, or am I just doing
something wrong?

perl -i -e '@_=<>; print "Just another Perl hacker,\n";' /dev/null
--
Andreas Gustafsson
Internet: gson@niksula.hut.fi
Voice: +358 0 563 5592

lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (05/14/91)

In article <1991May11.091442.11389@santra.uucp> gson@niksula.hut.fi (Andreas Gustafsson) writes:
: I am trying to munge some mailbox files in-place by using Perl with
: the -i option.  The file is accessed in a somewhat random fashion, so
: I want to read the whole file into an array using @array=<>.  It turns
: out that this doesn't work very well with the -i option.  Consider the
: following program:
: 
: #!/p/bin/perl -i.bak
: @lines=<>;
: for(@lines)
: { s/^/X /;
: }
: $;="\n";
: print @lines;
: 
: When running the above program with a text file "foo" as an argument,
: it correctly prepends "X " to each line in the file but instead of
: modifying the file in-place it prints the modified file on standard
: output, leaving an em does work as expected:
: The following program, which does not use <> in an array context,
: 
: #!/p/bin/perl -i.bak
: while(<>)
: { s/^/X /;
:   print;
: }
: 
: Versions 3.0pl37 and 4.003 both behave this way.  The man page says
: that with -i, "files processed by the <> construct are to be edited
: in-place", not "files processed by the _scalar_ <> construct ...".  Is
: this a bug in Perl, a bug in the man page, or am I just doing
: something wrong?

It says "files", not "file".  This implies that it has to make a
transition to a new output file each time <> makes a transition to
a new input file.  This also means that the transition to the final
EOF on input closes down the final output file.  Thus, there's no way
to use <> in an array context and still do inplace editing.

Look at this:

	@ARGV = ("foo","bar");
	@lines = <>;
	print @lines;

Is it supposed to remember where each line came from and put it back
into the correct file?  That would be a major headache to implement...

It is not difficult to deal with the filenames yourself, if you really
want to sling whole files around.

And in general, arguing from silence in the Perl man page is dangerous.  :-)

Larry