perl -pi with INPUT_RECORD_SEPARATOR=undef (bug?)

  • Thread starter hernan gonzalez
  • Start date
H

hernan gonzalez

This is very simple, and is driving me nuts.
I have a perl script which just reads using <> with no record
separator (from the docs: 'You may set $/ to "undef" to read through
the end of file') and prints.
It works ok .. but when used with the inplace editing (perl -pi) it
rotates the lines. (??)

See the test case below:
[tested with perl 5.8.7 on cygwin/winxp, and perl 5.8.0 on slackware
9.0]

/home/hjg $ cat trivial.pl

$/ = undef;
$t = <>;
print $t;

/home/hjg $ cat x.txt
line 1
line 2
line 3

/home/hjg $ ls -l x.txt
-rw-r--r-- 1 hjg hjg 21 May 7 17:27 x.txt

(21 bytes: 3 lines x 7 chars)

/home/hjg $ perl trivial.pl x.txt > x1.txt

/home/hjg $ cat x1.txt
line 1
line 2
line 3

(everything ok here... but now...)

/home/hjg $ perl -pi trivial.pl x.txt

/home/hjg $ cat x.txt
line 2
line 3
line 1

(??? lets try again)

/home/hjg $ perl -pi trivial.pl x.txt

/home/hjg $ cat x.txt
line 3
line 1
line 2

Could someone please tell me what the hell is happening here ??
Thanks!

Hernan
 
P

Paul Lalli

hernan said:
This is very simple, and is driving me nuts.
I have a perl script which just reads using <> with no record
separator (from the docs: 'You may set $/ to "undef" to read through
the end of file') and prints.
It works ok .. but when used with the inplace editing (perl -pi)

That statement right there is your misunderstanding. It is the -i
option, by itself, that enables inplace editing. The -p option is a
separate option that surrounds your code with the following loop:
while (<>) {
#your code here
} continue {
print
}
it rotates the lines. (??)

/home/hjg $ cat trivial.pl

$/ = undef;
$t = <>;
print $t;

/home/hjg $ cat x.txt
line 1
line 2
line 3

/home/hjg $ perl -pi trivial.pl x.txt

The two options you've used have effectively created this program:

local $^I = '';
while (<>) {
$/ = undef;
$t = <>;
print $t;
} continue {
print
}
__END__

Trace through that program and see what's happening
1) Set $^I, to enable inplace editing
2) Begin reading from ARGV. At this point, $/ is the default, so $_
gets set to "line 1\n"
3) Set $/ to undef
4) Read the remainder of the file (because $/ is undefined) into $t.
So $t gets "line 2\nline 3\n"
5) Prints the contents of $t (lines 2 and 3)
6) Prints the contents of $_ (line 1)
7) Loop terminates, as file has been read (ie, eof has been reached)
8) End.
/home/hjg $ cat x.txt
line 2
line 3
line 1

And that is the correct and expected result, as demonstrated above.
Could someone please tell me what the hell is happening here ??

Read
perldoc perlrun
for more on the various options
and
http://perldoc.perl.org/perlfaq5.html#How-can-I-use-Perl's-'-i'-option-from-within-a-program?
for more information on using "-i" within a program.

Paul Lalli
 
D

Dr.Ruud

hernan gonzalez schreef:
/home/hjg $ cat x.txt
line 2
line 3
line 1
[...]
Could someone please tell me what the hell is happening here ??
Thanks!

Look at the source:

perl -MO=Deparse -p -e '$/ = undef; $t = <>; print $t' x.txt

LINE: while (defined($_ = <ARGV>)) {
$/ = undef;
$t = <ARGV>;
print $t;
}
continue {
die "-p destination: $!\n" unless print $_;
}


The first line (line 1) gets read from x.txt, because of the "-p",
so $_ becomes "line 1\n".

Then $/ becomes undef, and the rest of the file ("line 2\nline 3\n")
is read into $t, and eof() becomes true.

That $t is printed. Then (see the continue-block) the $_ is printed.

So your bug is your usage of "-p". See `perldoc perlrun`.
 
H

hernan gonzalez

problem solved, and something learned..
thanks for both -very clear- answers!

Hernan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,058
Latest member
QQXCharlot

Latest Threads

Top