Strings and quoting methods
Remarks#
The version syntax doesn’t allow us to guard off versions that don’t exist yet, so this is a reminder for somebody to go back and edit them in once it lands( RE: Perl 5.26 ). The version guards rather need to have a “future” classification for tentative features that might be available to people brave enough to do a source checkout.
String Literal Quoting
String literals imply no escaping or interpolation ( with the exception of quoting string terminators )
print 'This is a string literal\n'; # emits a literal \ and n to terminal
print 'This literal contains a \'postraphe '; # emits the ' but not its preceding \
You can use alternative quoting mechanisms to avoid clashes:
print q/This is is a literal \' <-- 2 characters /; # prints both \ and '
print q^This is is a literal \' <-- 2 characters ^; # also
Certain chosen quote characters are “balanced”
print q{ This is a literal and I contain { parens! } }; # prints inner { }
Double-quoting
Double-quoted strings use interpolation and escaping – unlike single-quoted strings. To double-quote a string, use either double quotes "
or the qq
operator.
my $greeting = "Hello!\n";
print $greeting;
# => Hello! (followed by a linefeed)
my $bush = "They misunderestimated me."
print qq/As Bush once said: "$bush"\n/;
# => As Bush once said: "They misunderestimated me." (with linefeed)
The qq
is useful here, to avoid having to escape the quotation marks. Without it, we would have to write…
print "As Bush once said: \"$bush\"\n";
… which just isn’t as nice.
Perl doesn’t limit you to using a slash /
with qq
; you can use any (visible) character.
use feature 'say';
say qq/You can use slashes.../;
say qq{...or braces...};
say qq^...or hats...^;
say qq|...or pipes...|;
# say qq ...but not whitespace. ;
You can also interpolate arrays into strings.
use feature 'say';
my @letters = ('a', 'b', 'c');
say "I like these letters: @letters.";
# => I like these letters: a b c.
By default the values are space-separated – because the special variable $"
defaults to a single space. This can, of course, be changed.
use feature 'say';
my @letters = ('a', 'b', 'c');
{local $" = ", "; say "@letters"; } # a, b, c
If you prefer, you have the option to use English
and change $LIST_SEPARATOR
instead:
use v5.18; # English should be avoided on older Perls
use English;
my @letters = ('a', 'b', 'c');
{ local $LIST_SEPARATOR = "\n"; say "My favourite letters:\n\n@letters" }
For anything more complex than this, you should use a loop instead.
say "My favourite letters:";
say;
for my $letter (@letters) {
say " - $letter";
}
Interpolation does not work with hashes.
use feature 'say';
my %hash = ('a', 'b', 'c', 'd');
say "This doesn't work: %hash" # This doesn't work: %hash
Some code abuses interpolation of references – avoid it.
use feature 'say';
say "2 + 2 == @{[ 2 + 2 ]}"; # 2 + 2 = 4 (avoid this)
say "2 + 2 == ${\( 2 + 2 )}"; # 2 + 2 = 4 (avoid this)
The so-called “cart operator” causes perl to dereference @{ ... }
the array reference [ ... ]
that contains the expression that you want to interpolate, 2 + 2
. When you use this trick, Perl builds an anonymous array, then dereferences it and discards it.
The ${\( ... )}
version is somewhat less wasteful, but it still requires allocating memory and it is even harder to read.
Instead, consider writing:
say "2 + 2 == " . 2 + 2;
my $result = 2 + 2; say "2 + 2 == $result"
Heredocs
Large Multi-Line strings are burdensome to write.
my $variable = <<'EOF';
this block of text is interpreted literally,
no \'quotes matter, they're just text
only the trailing left-aligned EOF matters.
EOF
NB: Make sure you ignore stack-overflows syntax highlighter: It is very wrong.
And Interpolated Heredocs work the same way.
my $variable = <<"I Want it to End";
this block of text is interpreted.
quotes\nare interpreted, and $interpolations
get interpolated...
but still, left-aligned "I Want it to End" matters.
I Want it to End
Pending in 5.26.0* is an “Indented Heredoc” Syntax which trims left-padding off for you
my $variable = <<~"MuchNicer";
this block of text is interpreted.
quotes\nare interpreted, and $interpolations
get interpolated...
but still, left-aligned "I Want it to End" matters.
MuchNicer
Removing trailing newlines
The function chomp
will remove one newline character, if present, from each scalar passed to it. chomp
will mutate the original string and will return the number of characters removed
my $str = "Hello World\n\n";
my $removed = chomp($str);
print $str; # "Hello World\n"
print $removed; # 1
# chomp again, removing another newline
$removed = chomp $str;
print $str; # "Hello World"
print $removed; # 1
# chomp again, but no newline to remove
$removed = chomp $str;
print $str; # "Hello World"
print $removed; # 0
You can also chomp
more than one string at once:
my @strs = ("Hello\n", "World!\n\n"); # one newline in first string, two in second
my $removed = chomp(@strs); # @strs is now ("Hello", "World!\n")
print $removed; # 2
$removed = chomp(@strs); # @strs is now ("Hello", "World!")
print $removed; # 1
$removed = chomp(@strs); # @strs is still ("Hello", "World!")
print $removed; # 0
But usually, no one worries about how many newlines were removed, so chomp
is usually seen in void context, and usually due to having read lines from a file:
while (my $line = readline $fh)
{
chomp $line;
# now do something with $line
}
my @lines = readline $fh2;
chomp (@lines); # remove newline from end of each line