http://qs1969.pair.com?node_id=87365

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

monks, i was wondering if any of you could tell me why a while loop over the default filehandle with $/ set to undef when using inplace editing runs twice instead of once. for example:
open(X,"< test"); undef $/; while(<X>) { print "hello" }
prints only once as expected, but
$ARGV[0]="test"; $^I=""; undef $/; while(<>) { print "hello" }
prints twice regardless of how many lines in 'test' thanks

Replies are listed 'Best First'.
Re: inplace file editing
by ZZamboni (Curate) on Jun 11, 2001 at 05:38 UTC
    I think the difference does not have to do with the use of $^I, but with how $/=undef behaves when reading from the magic <> file handle. The following program:
    $^I=""; undef $/; while(<>) { print "hello:\n" }
    Behaves the same if I comment out the $^I line: it prints "hello" twice, except that when $^I="" it is printed to the file I give as argument, obliterating it. Printing $_ on each iteration shows that $_ contains '' (empty string) on the second iteration, so my guess is that setting $/ to undef somehow changes the way in which perl reads from <>, but I don't really have an answer...

    --ZZamboni

      sorry, what i meant to say was
      $ARGV[0]="test"; $^I=""; undef $/; while(<>) { print STDOUT "hello\n" }
      (which stops hello getting printed to the file)...but it still prints twice. can ANYONE help?
Re: inplace file editing
by Abigail (Deacon) on Jun 11, 2001 at 11:51 UTC
    Are you sure that that's all the code you have? Because I cannot reproduce what you are getting.
    $ cat p.pl #!/opt/perl/bin/perl -w use strict; $ARGV [0] = $0; $^I = ""; undef $/; while (<>) {print STDOUT "Hello\n"} __END__ $ ./p.pl Hello $
    Only one time....

    -- Abigail

Re: inplace file editing
by mattr (Curate) on Jun 11, 2001 at 17:58 UTC
    It took me a while to figure out what was going on. Here's my program:
    #!/usr/bin/perl $ARGV[0]="test"; $^I=""; undef $/; while(<>) { print STDOUT "hello\n" }
    $/ seems to work correctly, reading to the end of the file if set to undef. However, by setting $^I to the null string, Perl seems to think it is running as if at the command line. the "while(<>)" reads from the file named "test", but the print statement writes to that same file. I find that without STDOUT, file test is erased and filled with a single "hello". Using the STDOUT filehandle, the file is erased and set to 0 bytes. Do you see the same activity?

    What I don't get is by keeping the same program as above but inserting $^I=undef; just before the print statement inplace editing does not seem to get disabled, i.e. the file is overwritten anyway.

Re: inplace file editing
by Anonymous Monk on Jun 11, 2001 at 20:41 UTC
    abigail: yes, im sure thats the only code. with the same code as you on my box (perl 5.6.0) i get different output. here is a transcript.
    gotham:~# cat p.pl #!/usr/bin/perl -w use strict; $ARGV[0]=$0; $^I=""; undef $/; while(<>) { print STDOUT "hello\n" } gotham:~# perl p.pl hello hello gotham:~#
    weird, huh?
Re: inplace file editing
by Anonymous Monk on Jun 11, 2001 at 21:00 UTC
    UPDATE: btw, it prints only once if the file 'test' is empty but if it has any lines in it, it prints twice (which it shouldnt)
Re: inplace file editing
by mattr (Curate) on Jun 12, 2001 at 10:51 UTC
    (re Abigail your comment) ..really wierd, since when I paste in your last program verbatim Abigail the program erases itself (visible in directory but 0 bytes), this when run as perl p.pl or as ./p.pl.

    Somebody else figure this out? Or is this just attributed to bugs that got fixed in Perl..?

    bash-2.02# perl -V Summary of my perl5 (5.0 patchlevel 5 subversion 2) configuration: Platform: osname=linux, osvers=2.2.5, archname=i586-linux uname='linux fatou 2.2.5 #2 smp mon mar 29 17:28:58 mest 1999 i686 + unknown ' hint=recommended, useposix=true, d_sigaction=define usethreads=undef useperlio=undef d_sfio=undef Compiler: cc='cc', optimize='-O2 -pipe', gccversion=egcs-2.91.66 19990314 (e +gcs-1.1.2 release) cppflags='-Dbool=char -DHAS_BOOL -I/usr/local/include' ccflags ='-Dbool=char -DHAS_BOOL -I/usr/local/include' stdchar='char', d_stdstdio=define, usevfork=false intsize=4, longsize=4, ptrsize=4, doublesize=8 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +2 alignbytes=4, usemymalloc=n, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lposix -lcrypt libc=, so=so, useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynami +c' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Characteristics of this binary (from libperl): Built under linux Compiled at Apr 15 1999 05:11:26 @INC: /usr/lib/perl5/5.00502/i586-linux /usr/lib/perl5/5.00502 /usr/lib/perl5/site_perl/5.005/i586-linux /usr/lib/perl5/site_perl/5.005