in reply to Re: binmode i/o for perl -pi in-place editing
in thread binmode i/o for perl -pi in-place editing

oops, yes. Thanks. Either I didn't hit Next> enough times when I Super Searched before, or I had a typo, because I didn't find that or a few other similar ones (especially in place edit - how to do).

Tomorrow, I'll have to try the ARGVOUT filehandle from the latter, and the -Mopen=IN,:bytes,OUT,:bytes derived from the former, and see whether one or both help. The other thought I had, while driving home, was that maybe I could grab the select-returned filehandle, and see whether that's the current loop's output handle (I would think so; I'll test it out tomorrow)

And I'm really disappointed I didn't notice the ARGVOUT when reading perlrun, because it was literally just a few lines down from where I was reading in the perldocs, and I should have seen it. :-( Oh, well. Hopefully, good news tomorrow.

Replies are listed 'Best First'.
Re^3: binmode i/o for perl -pi in-place editing
by pryrt (Abbot) on Dec 08, 2016 at 16:20 UTC

    So, what I learned:

    • \*ARGV and ${^LAST_FH} do refer to the same file
    • \*ARGVOUT and my $sh = select; do refer to the same file
    • Almost sufficient: perl -pi.orig -e "binmode ARGV; binmode ARGVOUT; s/w/v/g" src.bin : seemed to confirm that source file and output file were same length.
    • I couldn't get perl -pi.orig -Mopen=IN,:bytes,OUT,:bytes -e "s/w/v/g" src.bin to work the same as the dual bin-mode (I tried with :raw vs :bytes, and only the IN or OUT or both...
    • Unfortunately, even with the binmode, I found it wasn't sufficient: changing the input file so the first null-separated record (aka "line") has all the various EOL-like sequences showed me wrong: perl -e "binmode STDOUT; $,=qq(\0); print qq(n\nr\rnr\n\rrn\r\nend), qw(encoded file), qq(r:\r\0n:\n\0nr:\n\r\0rn:\r\n), qw(with EOL-like sequences)" > src.binperl -pi pi.pl src.bin & dir src.bin* ⇒ the output is one byte shorter than the input, because the binmode(ARGV) is too late for the first read (as was mentioned in the binmode and one-liners). Also, I'd lost the $/=qq(\0) at some point in the BEGIN block; when I re-inserted that, I found it wasn't working (because the first record had only been reading to the first newline, instead of the first null, and thus masking the fact that binmode wasn't applied for the first read).
    • I tried doing some tricks with eof (with or without empty parentheses), to no avail.
    • I tried doing BEGIN { ...; binmode ARGV; }, but it didn't help

    At this point, I'm just going to give in do it without the magic -pi. It frustrates me that I cannot get this, but since I have a less magic way working, I guess I'll have to live with it.

      I still don't do Windows, but I do have a virtual machine with strawberry perl v5.20.2 installed.

      Unfortunately, even with the binmode, I found it wasn't sufficient: changing the input file so the first null-separated record (aka "line") has all the various EOL-like sequences showed me wrong: perl -e "binmode STDOUT; $,=qq(\0); print qq(n\nr\rnr\n\rrn\r\nend), qw(encoded file), qq(r:\r\0n:\n\0nr:\n\r\0rn:\r\n), qw(with EOL-like sequences)" > src.binperl -pi pi.pl src.bin & dir src.bin* ⇒ the output is one byte shorter than the input, because the binmode(ARGV) is too late for the first read (as was mentioned in the binmode and one-liners). Also, I'd lost the $/=qq(\0) at some point in the BEGIN block; when I re-inserted that, I found it wasn't working (because the first record had only been reading to the first newline, instead of the first null, and thus masking the fact that binmode wasn't applied for the first read).

      In your pi.bat (which you named windows cmd.exe in the OP) file I changed this line:

      - perl -pi.orig pi.pl src.bin + perl -Mopen=IO,:raw -pi.orig pi.pl src.bin

      and lo! both the original and the modified file have the same size, and identical content but for s/w/v/g. With your src.bin as per the above quotation, running perl -Mopen=IO,:raw -pi.bak -e "s/w/v/g" src.bin again produced the same result.

      Either you are getting your test cases mixed up, or something weird is happening. What perl version do you run?

      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

        ++shmem. Today, when I try either

        perl -Mopen=IO,:raw -pi.orig pi.pl src.bin

        or

        perl -Mopen=IN,:raw,OUT,:raw -pi.orig pi.pl src.bin

        ... it works (file length stays the same with the original). I could have sworn I'd tried the second version, but maybe I had mixed up my test cases, like you said. Good to know that it can actually be done using the -pi magic notation.

        Thanks again.