Bash: Execute command from variable without eval

bashshell-scripting

I have a problem with a script which should execute a curl command composed from the given arguments. It works if I use eval in the subshell, however, I would like to avoid that as it seems to be bad style according to this

Here is the relevant part of the script:

#!/bin/bash
COMMAND="curl -s -o /dev/null -w '%{http_code}' -X POST -H \"Content-Type:application/json\" -H \"Accept:application/json\" https://www.example.com/login -d '{\"username\":\"$1\",\"password\":\"$2\"}'"
echo $(eval $COMMAND)

With eval, I get 201 or 401 depending on the validity of the given credentials as expected. If I remove eval and use echo $($COMMAND) I get 400 which indicates a wrongly constructed data parameter.

Can someone explain to me, how I have to construct the command such that I can directly pass it to a subshell?

Best Answer

You may use backticks or nesting to avoid using eval.

Backticks

$ var=\`curl -s -o /dev/null -w '%{http_code}' -X POST -H \"Content-Type:application/json\" -H \"Accept:application/json\" https://www.example.com/login -d '{\"username\":\"$1\",\"password\":\"$2\"}'"\`

Nesting

$ var = $(curl -s -o /dev/null -w '%{http_code}' -X POST -H \"Content-Type:application/json\" -H \"Accept:application/json\" https://www.example.com/login -d '{\"username\":\"$1\",\"password\":\"$2\"}'")

Nesting is supported on the vast majority of shells and more readable than backticks.