I am trying to run a command from a variable in shell script. The shell being used is bash shell.
The file exp
contains:
abcdef
Executing the following command:
sed s/b/\ / exp
...produces the output:
a cdef
But executing:
cmd="sed s/b/\ / exp"
echo $cmd
$cmd
...produces the following error:
sed s/b/\ / exp
sed: -e expression #1, char 5: unterminated `s' command
I can see that adding eval
in front of the execution works. But I cannot understand why. Can you explain why one method is working and the other is not working?
Here, the first line of the script i.e. “#!/bin/bash” shows that this file is in fact a Bash file. Then we have created a variable named “test” and have assigned it the value “$(echo “Hi there!”)”. Whenever you want to store the command in a variable, you have to type that command preceded by a “$” symbol.
To store the output of a command in a variable, you can use the shell command substitution feature in the forms below: variable_name=$(command) variable_name=$(command [option ...] arg1 arg2 ...) OR variable_name='command' variable_name='command [option ...]
The problem you are having is that the space itself is not being interpreted properly by Bash.
See how it works well if you replace the b
with another character, say X
:
$ cmd="sed s/b/X/ exp"
$ $cmd
aXcdef
So the workaround is to use the hexadecimal for the space, which is 20
:
$ cmd="sed s/b/\x20/ exp"
$ $cmd
a cdef
Or to use eval
to execute the command itself:
$ cmd="sed s/b/\ / exp"
$ eval "$cmd"
a cdef
As Tom Fenech suggested, storing commands in variables in not a good approach, as described in I'm trying to put a command in a variable, but the complex cases always fail!. It can work sometimes but in other cases can produce unpredictable results. An alternative is to consider using a function.
Finally, note eval
can come handy in cases like this, only that being very careful on what is stored. Some good reading: Variable as command; eval vs bash -c.
It looks like a quoting issue:
cmd="sed s/b/\ / exp"
makes $cmd
hold a sequence of characters with no special meaning. So your \
does not escape your space.
eval
treats that sequence of characters as a command, and re-assign the special meaning to your \
.
See also: Preserving quotes in bash function parameters
If you need the output in the variable then use,
cmd=$(sed 's/b/ /' exp)
Like @thomas says, If you are using the variable you can use the double quotes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With