Reputation: 71
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?
Upvotes: 7
Views: 566
Reputation: 289775
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.
Upvotes: 6
Reputation: 16368
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
Upvotes: 3
Reputation: 4041
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.
Upvotes: 1
Reputation: 41456
This should do:
cmd=$(sed "s/b/\ /" exp)
To store data in variable use var=$(commands)
Upvotes: 0
Reputation: 54525
If you quote the sed parameters, the script is easier to read, and backslashes are needed only to escape special characters (such as backslash and the double-quotes):
cmd=$(sed "s/b/ /" exp)
If you use single-quotes, that reduces the need for escaping more -- but prevents you from using variables such as this:
xxx=something
cmd=$(sed "s/b/$xxx/" exp)
Upvotes: 0