hemlock hemlock - 5 months ago 8
Perl Question

Why does my Perl one-liner containing an escaped $ not work inside Bash backticks?

I'm trying search for a

$
in a text document using a Perl one-liner in a Bash script. I suspect it is treating the
$
as a variable.

This is my code:

ITEMVALUE=`perl -ne 'print /\$.*/g' file.txt`


The text looks something like this:

a bunch of random text
$80
a bunch of random text


I want to extract the
$80
only. Why isn't this working, and how do I retrieve the desired text?

Answer

From the Bash manual:

Command Substitution

Command substitution allows the output of a command to replace the command name. There are two forms:

$(command)

or

`command` 

...

When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \ ... When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

(emphasis added)

Bash is treating the \ in \$ as an escape sequence, so

ITEMVALUE=`perl -ne 'print /\$.*/g' file.txt`

actually runs

perl -ne 'print /$.*/g' file.txt

$. is a Perl built-in variable representing the current line number, so the regex becomes /1*/ for the first line, /2*/ for the second line, and so on. You'll get output for any line containing its own line number.

You can see this using Perl's re pragma:

$ ITEMVALUE=`perl -Mre=debug -ne 'print /\$.*/g' file.txt`
Compiling REx "1*"
...
Compiling REx "2*"
...

To fix, use the $(command) form of command substitution, which is generally preferred anyway:

ITEMVALUE=$(perl -ne 'print /\$.*/g' file.txt)