107

In Perl most of my print statements take the form

print "hello." . "\n";

Is there a nice way to avoid keeping all the pesky "\n"s lying around?

I know I could make a new function such as myprint that automatically appends \n, but it would be nice if I could override the existing print.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
Mike
  • 58,961
  • 76
  • 175
  • 221
  • 12
    If your answer includes $\ please make sure it comes with a list of caveats about setting global variables with invisible effect. While its very clever and technically answers the question, its also very dangerous to hand unqualified to a newbie. – Schwern May 24 '10 at 19:07
  • 1
    `perldoc perlvar` describes most of the caveats, why belabor them here? – David M May 24 '10 at 19:32
  • 7
    @David, because some random hacker will google the answers here instead of perldoc, get satisfied with them, and won't even know about the caveats! – P Shved May 24 '10 at 19:35
  • 3
    That's exactly the sort of bizarre reasoning that has resulted in my iron having a warning label that I should not iron clothes while I am wearing them. – David M May 25 '10 at 00:31
  • 9
    Real-life tools have physical limitations that are reasonably well-understood by people who have lived their lives in the physical world. Software tools are bound by no such limitations, and there aren't any rules. They can do anything, and frequently behave outside expectations, especially for beginners who have not learned the boundaries of reasonable expectations yet. – Ether May 25 '10 at 15:05
  • 1
    Yet, most people agree that it's a inevitable painful lesson in the real world that a child is going to touch a hot stove. Explain to that child all you like that stoves get hot, but a) the child will eventually touch something hot and b) that lesson will outweigh all the explaining in the world. Perhaps I'm making too much of the analog between hot stoves and special Perl variables, but no one really respects those special Perl variables until they get burned a couple of times. – David M May 25 '10 at 15:25
  • @DavidM This is not "irons are hot" this is "if you leave this iron on too long it will burn through the chord and start a fire; nobody should use this iron because it is a fire hazard". If you hand it to someone and say "this is an iron, it will make your shirts smooth" they'll expect it as safe as any other iron until their house burns down. Unlike burning your hand on a hot iron, the consequences of a faulty iron, like an abused global variable, are unexpected, delayed and unpredictable. – Schwern May 25 '10 at 23:21
  • @Schwern I guess we'll agree to disagree then. I think you're overstating the worst case of setting $\ (or probably any other special variable). I agree that I wouldn't use $\ in this instance, but there are plenty of occasions upon which setting a special variable makes a complicated program much simpler. – David M May 26 '10 at 00:58

9 Answers9

103

Raku (Perl 6) has the say function that automatically appends \n.

You can also use say in Perl 5.10 or 5.12 if you add

use feature qw(say);

to the beginning of your program. Or you can use Modern::Perl to get this and other features.

See perldoc feature for more details.

noraj
  • 3,964
  • 1
  • 30
  • 38
Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • 7
    In fact, all you have to do is `use 5.012;` or `use 5.010;` to get it if you're running those newer `perl`s. – Robert P May 25 '10 at 00:06
  • Isn't it safe to assume that unless Perl 6 is specifically mentioned that the question refers to Perl 5? – wobbily_col Nov 22 '17 at 12:18
50

You can use the -l option in the she-bang header:

#!/usr/bin/perl -l

$text = "hello";

print $text;
print $text;

Output:

hello
hello

See "-l[octnum]" in perlrun(1) for details.

U. Windl
  • 3,480
  • 26
  • 54
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • 3
    Very nice. More on `perl` options, including what `-l` is doing, [here](http://www.perl.com/pub/2004/08/09/commandline.html). – ruffin Jan 12 '15 at 17:10
25

If Perl 5.10+ is not an option, here is a quick and dirty approximation. It's not exactly the same, since say has some magic when its first arg is a handle, but for printing to STDOUT:

sub say {print @_, "\n"}

say 'hello';
Eric Strom
  • 39,821
  • 2
  • 80
  • 152
21

The way you're writing your print statement is unnecessarily verbose. There's no need to separate the newline into its own string. This is sufficient.

print "hello.\n";

This realization will probably make your coding easier in general.

In addition to using use feature "say" or use 5.10.0 or use Modern::Perl to get the built in say feature, I'm going to pimp perl5i which turns on a lot of sensible missing Perl 5 features by default.

Schwern
  • 153,029
  • 25
  • 195
  • 336
10

Perhaps you want to change your output record separator to linefeed with:

local $\ = "\n";

$ perl -e 'print q{hello};print q{goodbye}' | od -c
0000000    h   e   l   l   o   g   o   o   d   b   y   e                
0000014
$ perl -e '$\ = qq{\n}; print q{hello};print q{goodbye}' | od -c
0000000    h   e   l   l   o  \n   g   o   o   d   b   y   e  \n        
0000016

Update: my answer speaks to capability rather than advisability. I don't regard adding "\n" at the end of lines to be a "pesky" chore, but if someone really wants to avoid them, this is one way. If I had to maintain a bit of code that uses this technique, I'd probably refactor it out pronto.

Schwern
  • 153,029
  • 25
  • 195
  • 336
David M
  • 4,325
  • 2
  • 28
  • 40
  • 7
    No, please don't do that. While technically a correct answer, using a special variable for something as trivial as this is a maintenance burden down the road. – tsee May 25 '10 at 07:43
  • 1
    @tsee I agree completely, actually. As I edited my answer to indicate, my answer describes the capability, even if one wouldn't recommend it as a general practice. – David M May 25 '10 at 15:17
  • 1
    The real danger comes from the fact that all code will now add newlines, even code in other people's modules that weren't expecting it. Imagine networking code that would have sent the message `"helo\r\n"` that now sends `"helo\r\n\n"`. – Chas. Owens Jun 05 '10 at 14:15
  • 1
    Of course you could always make it local to avoid affecting other code, but still want to make your subroutine look a little cleaner: `local $\ = "\n";` – redbmk Mar 23 '12 at 19:33
  • Using the command flag `-l` is great for command line one-liners (see http://perldoc.perl.org/perlrun.html#Command-Switches). I wouldn't recommend it in any larger program. – djd Jun 13 '12 at 05:15
6

Here's what I found at https://perldoc.perl.org/perlvar.html:

$\ The output record separator for the print operator. If defined, this value is printed after the last of print's arguments. Default is undef.

You cannot call output_record_separator() on a handle, only as a static method. See IO::Handle.

Mnemonic: you set $\ instead of adding "\n" at the end of the print. Also, it's just like $/ , but it's what you get "back" from Perl.

example:

$\ = "\n";
print "a newline will be appended to the end of this line automatically";
hofergabriel
  • 69
  • 1
  • 2
3

In Raku (Perl 6) there is, the say function.

noraj
  • 3,964
  • 1
  • 30
  • 38
Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
1

If you're stuck with pre-5.10, then the solutions provided above will not fully replicate the say function. For example

sub say { print @_, "\n"; }

Will not work with invocations such as

say for @arr;

or

for (@arr) {
    say;
}

... because the above function does not act on the implicit global $_ like print and the real say function.

To more closely replicate the perl 5.10+ say you want this function

sub say {
    if (@_) { print @_, "\n"; }
    else { print $_, "\n"; }
}

Which now acts like this

my @arr = qw( alpha beta gamma );
say @arr;
# OUTPUT
# alphabetagamma
#
say for @arr;
# OUTPUT
# alpha
# beta
# gamma
#

The say builtin in perl6 behaves a little differently. Invoking it with say @arr or @arr.say will not just concatenate the array items, but instead prints them separated with the list separator. To replicate this in perl5 you would do this

sub say {
    if (@_) { print join($", @_) . "\n"; }
    else { print $_ . "\n"; }
}

$" is the global list separator variable, or if you're using English.pm then is is $LIST_SEPARATOR

It will now act more like perl6, like so

say @arr;
# OUTPUT
# alpha beta gamma
#
elcaro
  • 2,227
  • 13
  • 15
-1

As requested:

sub myprint { print @_, "\n"; }
myprint "foo", 3 . 'bar'

And what was the actual problem?

Maybe try understanding the language you have before trying to change it.

Man perlvar(1) says: "Within a subroutine the array @_ contains the parameters passed to that subroutine."

U. Windl
  • 3,480
  • 26
  • 54