Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get a “Can't find string terminator” error only when the command is in a variable?

Tags:

bash

shell

I wrote a simple shell script to get the version of Perl modules installed on a server and I keep receiving the following error:

Can't find string terminator "'" anywhere before EOF at -e line 1.

Here is my script:

#!/bin/sh
#
mod_name="Sub::Uplevel"
tmp1="perl -M$mod_name -e 'print \"\$$mod_name::VERSION\"'"
echo $tmp1
$tmp1

If I just directly run the echo'd line (perl -MSub::Uplevel -e 'print "$Sub::Uplevel::VERSION"'), it works. Why doesn't the line work when its run from the variable $tmp1?

like image 973
GoinOff Avatar asked Nov 19 '25 04:11

GoinOff


2 Answers

In place of just $tmp1, eval works:

eval "$tmp1"

That's because splitting a variable into words (for arguments) is done strictly by splitting on $IFS, not the normal input-parsing. eval forces the normal input parsing.

How did I figure this out?

Change your tmp1= line to put an echo in front, and you get:

perl -MSub::Uplevel -e 'print "$Sub::Uplevel::VERSION"'

Note that the ' are still there, which you wouldn't expect. If you write a quick script:

#!/bin/sh

for a in "$@"; do
    echo "arg: $a"
done

and put a call to that in place of echo, you find how the arguments are really split:

arg: perl
arg: -MSub::Uplevel
arg: -e
arg: 'print
arg: "$Sub::Uplevel::VERSION"'

So, you can see that's splitting on spaces, so IFS.

like image 125
derobert Avatar answered Nov 21 '25 17:11

derobert


It's always better to construct commands using bash arrays. That will keep arguments with whitespace properly grouped:

#!/bin/bash
mod_name="Sub::Uplevel"
perl_script=$(printf 'print "$%s::VERSION"' $mod_name)
tmp1=(perl -M$mod_name -e "$perl_script")
echo "${tmp1[@]}"
output=$( "${tmp1[@]}" )

Arrays are a bash feature, so the shebang line must reference bash not sh.

like image 22
glenn jackman Avatar answered Nov 21 '25 19:11

glenn jackman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!