Perl Part I · Module 4 · Strings and Text
String Interpolation
Putting a variable straight inside double quotes is the feature Perl programmers reach for most, and it works so smoothly that the one hard question goes unasked: when Perl scans a string and meets a dollar sign, how much of what follows does it treat as the name? A dot ends the name, so a filename works. An underscore does not, so a suffix produces a compile error about a variable you never wrote. And an apostrophe does something stranger than either — it is read as an old-style package separator, so a possessive silently loses the value entirely and the script still exits zero. This chapter answers the question once, with the brace syntax that removes the guesswork.
Foundation14 min readPerlPart IFundamentalsStringsInterpolationDebugging
Part I · Module 4 · Chapter 4.2 · String Interpolation
1. The Ordinary Case
use strict;
use warnings;
my $block = "alu";
my $passed = 177;
print "block $block passed $passed tests\n";block alu passed 177 testsPerl scanned the string, met $block, replaced it with alu, met $passed, replaced it with 177, and printed the result. That is interpolation, and for most strings it is all you need to know.
It is also equivalent to concatenating the pieces, as Chapter 3.3 §2 showed — "block " . $block . " passed " and so on. Interpolation is preferred for a sentence because the quoted string looks like its own output.
2. Where Does the Name End?
This is the question the chapter exists for. Perl has to decide how many characters after the $ belong to the variable name, and the rule is: a name continues through letters, digits and underscores, and stops at anything else.
Most punctuation therefore ends it cleanly:
use strict;
use warnings;
my $b = "alu";
print "dot: $b.log\n";
print "slash: /proj/$b/syn\n";
print "dash: $b-top\n";
print "colon: $b:1\n";dot: alu.log
slash: /proj/alu/syn
dash: alu-top
colon: alu:1A filename, a path, a hyphenated name and a colon-separated field all work with no special effort, because . / - and : are not name characters.
The underscore is not punctuation
use strict;
use warnings;
my $b = "alu";
print "$b_top\n";Global symbol "$b_top" requires explicit package name (did you forget to declare "my $b_top"?) at underscore.pl line 6.
Execution of underscore.pl aborted due to compilation errors.Perl read the name as $b_top — one name, including the underscore — found no such variable, and use strict refused to compile the file.
This failure is the good kind: loud, at compile time, and nothing ran. Chapter 1.10 is why. Without use strict the same line would have printed an empty string.
3. ${...} Says Where the Name Ends
use strict;
use warnings;
my $b = "alu";
print "braced: ${b}_top\n";
print "plural: ${b}s\n";braced: alu_top
plural: alusThe braces delimit the name explicitly, so the characters after } are text no matter what they are. ${b} is the same variable as $b — the braces add no meaning beyond marking where the name stops.
Use them whenever the character after a variable could be read as part of the name: an underscore, a letter, or a digit. The two common cases are a suffix (${block}_top) and a plural (${block}s).
4. The Apostrophe Trap
This one deserves its own section, because it loses data and exits zero.
use strict;
use warnings;
my $name = "Ravi";
print "$name's run\n"; runOld package separator used in string at apos.pl line 6.
(Did you mean "$name\'s" instead?)
Name "name::s" used only once: possible typo at apos.pl line 6.
Use of uninitialized value $name::s in concatenation (.) or string at apos.pl line 6.0The output is " run". Ravi is gone entirely, and the program reported success.
The reason is historical: in old Perl, ' was a package separator, the way :: is today. So $name's is read as the variable $name::s — package name, variable s — which does not exist, is undefined, and interpolates as nothing.
Two things to take from this:
use strictdid not stop it. A package-qualified name is exempt from the declaration requirement, because a package variable is a legitimate thing to refer to. So this is the one interpolation trap that compiles and runs.use warningsis the entire defence, and it was generous — three messages, including Perl literally suggesting the fix.
The fix, measured:
use strict;
use warnings;
my $name = "Ravi";
print "${name}'s run\n";Ravi's run\' as Perl suggested also works. The braces are clearer and are the same tool as §3, so prefer them.
5. @ Interpolates Too
A string containing an email address or a shell array reference hits the array sigil:
use strict;
use warnings;
print "mail: user@example.com\n";Possible unintended interpolation of @example in string at at-sign.pl line 4.
Global symbol "@example" requires explicit package name (did you forget to declare "my @example"?) at at-sign.pl line 4.
Execution of at-sign.pl aborted due to compilation errors.Arrays are Module 5's subject, but the scanning rule is the same: @ starts a name, so @example was read as an array. Under use strict that is a compile error, and the first message is Perl guessing correctly at your intent.
Unlike §4, this one fails loudly. Escape the sigil, or single-quote the string:
use strict;
use warnings;
print "mail: user\@example.com\n";
print 'mail: user@example.com', "\n";mail: user@example.com
mail: user@example.comBoth work. Which to prefer follows Chapter 4.1 §5: if the string has nothing else to interpolate, single quotes say so.
A lone sigil that cannot start a name is left alone:
use strict;
use warnings;
print "cost 5\$ and a bare @ here\n";cost 5$ and a bare @ hereThat works, but relying on it is fragile — a later edit that puts a letter after the sigil changes the meaning of the line. Escape them deliberately.
6. An Undefined Variable Interpolates as Nothing
use strict;
use warnings;
my $block = "alu";
my $stage;
print "report: $block $stage done\n";report: alu doneUse of uninitialized value $stage in concatenation (.) or string at undef-in-string.pl line 7.The output has two spaces where $stage should have been, and that is the only visible trace. It is a readable sentence; nothing about report: alu done announces that a field is missing.
This is the same message and the same argument as Chapter 3.3 §5, now in a report line rather than a filename. Chapter 2.7 is the chapter on definedness, and the practical rule from it applies here: if a field may legitimately be absent, supply a visible placeholder rather than letting it interpolate to nothing.
7. What Does Not Interpolate
A common misconception, settled by measurement:
use strict;
use warnings;
my $s = "alu";
print "uc is: uc($s)\n";uc is: uc(alu)The function was not called. Perl interpolated $s and left the letters uc( and ) as text. Interpolation substitutes variables, not expressions.
The same applies to arithmetic: "total: $a + $b" prints both values with a literal plus sign between them, not their sum.
When you genuinely need an expression inside a string, there is an idiom:
use strict;
use warnings;
my $passed = 177;
my $total = 184;
print "rate: @{[ sprintf('%.1f', $passed / $total * 100) ]}%\n";
print "sum : @{[ $passed + 7 ]}\n";rate: 96.2%
sum : 184This is the form Chapter 2.11 §4 asked you to recognise rather than reach for, and the advice stands. It relies on machinery from Module 7, and the clearer alternative is almost always to compute the value into a variable on the line before:
my $rate = sprintf('%.1f', $passed / $total * 100);
print "rate: $rate%\n";Two lines, no idiom, and the intermediate value now has a name you can print when something looks wrong.
Note also that "$array[0]" and "$hash{key}" do interpolate — element access is part of the name syntax. Those belong to Module 5 and Module 6 respectively and are mentioned here only so the behaviour is not a surprise when you meet it.
8. Why This Matters in Engineering Work
Building a filename from parts. "${block}_${test}.log" is the shape, and every one of those braces is earning its place: without them $block_ and $test_ would be read as names that do not exist. This is the single most common real use of ${...}.
Report lines with optional fields. A summary line assembled from parsed values will interpolate an absent field as nothing, giving a double space in a sentence that still reads correctly. The warning on STDERR is the only signal, which is an argument for keeping STDERR in your logs — and Chapter 3.9 made the same point about a different failure.
Anything containing an apostrophe. A possessive in a message — "$owner's area" — silently drops the value. It is worth knowing this one by sight, because the output is grammatical and the three warnings are easy to scroll past.
Addresses, globs and shell text. Any string with an @ or a literal $ needs either an escape or single quotes. Under use strict you will be told, which makes this the least dangerous case in the chapter.
9. Common Mistakes
Letting an underscore run into a variable name. "$block_top" is a name, not a name plus text. Write "${block}_top".
Writing a possessive. "$name's" is $name::s. Write "${name}'s".
Forgetting to escape @ in an address. It is a compile error under use strict.
Expecting a function call inside a string to run. "uc($s)" prints the letters. Compute first, interpolate second.
Expecting arithmetic inside a string to be evaluated. "$a + $b" is two values and a plus sign.
Ignoring an uninitialized-value warning on a report line. The sentence still reads correctly, which is exactly the problem.
Relying on a sigil being "obviously" literal. It is literal only because of what follows it, and a later edit can change that.
10. Exercise
Exercise 1 — find the boundary. With my $b = "alu";, predict what each prints before running: "$b.log", "$b-top", "$b/syn", "$b2", "$b_top". Then run all five and say which two needed braces and why.
Exercise 2 — the apostrophe. Run the §4 script. Record STDOUT, all three STDERR lines and the exit status. Then explain in one sentence what variable Perl actually looked for, and fix the line two different ways.
Exercise 3 — build a log name. Given my $block = "alu"; and my $test = "smoke";, produce alu_smoke.log in a single interpolated string. Then remove the braces and record the exact compile error.
Exercise 4 — the missing field. Write a script with three variables where the middle one is declared but never assigned, interpolate all three into a sentence, and capture STDOUT and STDERR separately. Say what a reader of STDOUT alone would conclude, then change the line so an absent value prints as UNKNOWN.
Exercise 5 — the address. Write print "owner: ci@vlsimentor.com\n"; and record what happens. Fix it twice — once with an escape, once by changing the quotes — and say which you would commit.
Exercise 6 — no calls in strings. Predict and then measure what "len is length($s)" prints with my $s = "alu";. Then rewrite it so the length actually appears, using the two-line form from §7, and say why that form is preferable to the @{[ ]} idiom here.
11. Summary
- Double quotes replace a variable with its value; single quotes do not — Chapter 4.1.
- A name continues through letters, digits and underscores and stops at anything else, so
./-:end it cleanly and_does not. ${name}marks where the name ends and is the fix for a suffix or a plural."$name's"is read as$name::sbecause'was an old package separator. It loses the value, exits0, and onlyuse warningsreports it.@interpolates too, so an address is a compile error underuse strictuntil escaped.- An undefined variable interpolates as nothing, leaving a readable sentence with a missing field and a warning on STDERR.
- Function calls and arithmetic do not interpolate. Compute into a variable first.
Chapter 4.3 covers the other half of what double quotes do — the backslash sequences — including the ones that change case mid-string and the one that makes text safe to use as a pattern.
Where this fits
Part of the Perl curriculum.
