'How can I print just a unix newline in Perl on Win32?

By default, perl prints \r\n in a win32 environment. How can I override this? I'm using perl to make some changes to some source code in a repository, and I don't want to change all the newline characters.

I tried changing the output record separator but with no luck.

Thanks!

Edit: Wanted to include a code sample - I'm doing a search and replace over some files that follow a relatively straightforward pattern like this:

#!/usr/bin/perl
# test.pl

use strict;
use warnings;

$/ = undef;
$\ = "\n"; 
$^I=".old~";

while (<>) {
  while (s/hello/world/) {

  }
  print;
}

This should replace any instances of "hello" with "world" for any files passed on the cmd line.

Edit 2: I tried the binmode as suggested without any luck initially. I delved a bit more and found that $^I (the inplace edit special variable) was overriding binmode. Any work around to still be able to use the inplace edit?

Edit 3: As Sinan points out below, I needed to use binmode ARGVOUT with $^I instead of binmode STDOUT in my example. Thanks.



Solution 1:[1]

Does binmode( STDOUT ) work?

Solution 2:[2]

Re: your question about the binmode being lost when $^I opens a new output handle, you could solve this with the open pragma:

use open OUT => ':raw';

which will force all filehandles opened for writing to have the ':raw' PerlIO layer (equivalent to binmode with no argument) to apply to them. Just take care if you're opening anything else for output that you apply :crlf or any other layer as needed.

Solution 3:[3]

The data you are reading in contains line endings, so you're getting them back out again. You can strip them off yourself with chomp, then add your own ending back, provided you have set binmode as Sinan describes::

while (<>) {
    binmode;
    chomp;        # strip off \r\n
    while (s/search/replace/) {
        # ...
    }
    print;
    print "\n";   # add your own line ending back
}

Solution 4:[4]

By default, perl prints \r\n in a win32 environment. How can I override this?

I ended up creating my own file and setting binmode(fh) specifically. I could not get STDOUT (or ARGVOUT) to work reliably under both Windows 10 using perl 5.8.8 and Windows 7 with perl 5.14.4.

perl -e 'open(fh, ">x"); binmode(fh); print fh "\n";' ; od -c x
0000000  \n

Sometimes the binmode(fh) was needed here and sometimes it seemed to be the default.

I could not get binmode(STDOUT) to be work reliably. Some of the following did output just \n under Windows:

perl -e 'binmode(ARGVOUT); print "\n";' | od -c
perl -e 'binmode(STDOUT); print "\n";' | od -c
perl -e 'binmode(STDOUT); syswrite(STDOUT, "\n");' | od -c

... but then not when the output was going to a file. The following still spat out \r \n.

perl -e 'binmode(STDOUT); print "\n";' > x ; od -c x
perl -e 'binmode(ARGVOUT); print "\n";' > x ; od -c x

Interestingly, the following worked when piping to cat which then writes to a file. Perl must be seeing if STDOUT is a terminal, file, or pipe and enabling the cr-lf layer or not. Why a pipe is binary but a file is not is an interesting decision. There are also differences between running perl interactively from the command-line and running it from a script with the same args and redirects.

perl -e 'binmode(STDOUT); print "\n";' | cat > x ; od -c x

Noticed that I tried print and syswrite. I was surprised that syswrite didn't give me a direct layer to the file-handle. I also tried to copy the STDOUT file-handle and set binmode on that new file-handle but that didn't work either. PERLIO environmental variable didn't help either. The use out => ":raw"; worked under Windows 10 perl 5.8.8 but not Windows 7 perl 5.14.4 when redirected to an output file.

Btw, I wasn't doing a print "\n"; in my code when I stumbled over this problem. I was doing a print of pack("c", $num); where $num happened to be 10. Imagine my surprise when my binary file was corrupted by \rs.

Porting sucks!

Solution 5:[5]

A unix newline is a LINEFEED character, which is ASCII code 10.

print "\012";

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PP.
Solution 2 hobbs
Solution 3
Solution 4
Solution 5 Chris Cleeland