perlnewlinettypty

Where does this \r\n come from when I redirect STDOUT to a PTY in Perl?


With the following code:

use strict;
use warnings;
use utf8;

use IO::Pty;
use Data::Dump qw(pp);

my $pty = IO::Pty->new;
open *STDOUT, '>&', $pty->slave;

if ( my $pid = open *STDOUT, '|-' ) {
  # parent
  my $str = "foo\n";
  print {*STDERR} "parent [1]: ", pp($str), "\n";
  print {*STDOUT} $str;
  my $line = <$pty>;
  print {*STDERR} "parent [2]: ", pp($line), "\n";
} else {
  # child
  while (<>) {
    print {*STDERR} "child [1]: ", pp($_), "\n";
    s/foo/bar/;
    print {*STDERR} "child [2]: ", pp($_), "\n";
    print $_;
  } ## end while (<>)
  exit;
} ## end else [ if ( my $pid = open *STDOUT...)]

The output I get is:

parent [1]: "foo\n"
child [1]: "foo\n"
child [2]: "bar\n"
parent [2]: "bar\r\n"

But on the last line I expected to receive "bar\n". Also, I'm running Perl under Linux, so shouldn't this LF to CRLF nonsense be a non-issue?


Solution

  • \r and \n are "control characters". What are "control characters" controlling? A typewriter. Well, it used to.

    TTYs pre-date computers, going back to telegraphs. TTY stands for teletype; literally a typewriter that types the output. As it was a typewriter, it needed to be told to slide (return) the print head (carriage) back to the first column of the page, and then advance the paper to the next line. \r\n.

    Now that's baked into the tty protocol. Even though technology has moved on, it's still acting like it's talking to a typewriter.

    See also Why in the output of script (1) the newline is CR + LF (dos-style)?