Rudolf
Rudolf

Reputation: 143

Bash, Escaping quotes in command construction,

I have an array of numbers - sipPeers.

I want to iterate trough that array and pass each value into the command

asterisk -rx "sip show peer 1234" - where 1234 is obviously an extension.

The output of sip show peer is piped and manipulated twice to output one value which I want to store in a second array sipUserAgent.

temp="asterisk -rx \"sip show peer "${sipPeers[q]}"\" | grep Useragent |  awk \'{print$3}\'" #(1)
echo $temp #(2)
sipUserAgent[q]=$($temp) #(3)

The output of one iteration yields the constructed command as a string (2) and the tries to execute it (3):

asterisk -rx "sip show peer 564" | grep Useragent | awk '{print }'
No such command '"sip' (type 'core show help sip' for other possible commands)

If I copy and paste the echo'd command it runs, but when the script executes I get that error. Somewhere the " character changes meaning when the scipt executes it?

Upvotes: 1

Views: 414

Answers (3)

H.-Dirk Schmitt
H.-Dirk Schmitt

Reputation: 1169

1st problem

In the step (1) you write: awk \'{print$3}\'

In the output of (2) you receive: awk '{print }'

The problem is an missed escape of $3

Try is again with awk \'{print\$3}\' in (1)

2nd problem

sipUserAgent[q]=$($temp) tries to invoke a command asterisk_-rx...

This is surely not what you want. The solution is to use eval - see help eval for more informations.

example

cmd="echo TEST"
$(${cmd})

gives:

TEST: command not found

cmd="echo TEST"
eval ${cmd}

gives:

TEST

Note about code style

If possible it is better to avoid complex command creation and execution via eval. Better is to write more simple code, if applicable. So you should use (as also mentioned by Gordon Davisson in another answer):

sipUserAgent[q]=$(asterisk -rx "sip show peer ${sipPeers[q]}" \
 | grep Useragent \
 |  awk '{print $3}' \
)    

Upvotes: 1

Gordon Davisson
Gordon Davisson

Reputation: 125818

Don't try to store the command in a variable before executing it. There are all sorts of problems with doing this, and you're running into several of them (see BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!). Just put the pipeline directly inside $( ... ) where it belongs:

sipUserAgent[q]=$(asterisk -rx "sip show peer ${sipPeers[q]}" | grep Useragent |  awk '{print $3}')

Upvotes: 3

user000001
user000001

Reputation: 33327

I am not aware of a way to escape quotes during command substitution, but a workaround is to use eval. See the following example:

$ cat test.sh 
echo "$1"
$ temp="./test.sh \"2 34 434\" "
$ echo "$temp"
./test.sh "2 34 434"
$ result=$(eval $temp)
$ echo "$result"
2 34 434
$ result=$($temp)
$ echo "$result"
"2

Note that using eval is generally considered bad practice in most situations, if you can avoid it.

Upvotes: 0

Related Questions