I am writing a script which executes a number of programs with arguments. To simplify it as much as possible, consider the following example:
programs=( "ls" "echo" )
declare -A parameters
parameters["ls"]="-l /tmp/foo"
parameters["echo"]="Hello"
for program in "${programs[@]}"
do
$program ${parameters[$program]}
done
This works fine as long as there are no spaces in the arguments. Of course, escaping strings has been discussed before, so I tried all of the different ways I could find here on StackExchange and some other pages. However, I could not find a solution which works in my case which uses associative arrays. For example, when I want to get a listing of "/tmp/foo bar", neither this
parameters["ls"]="-l /tmp/foo bar"
nor this
parameters["ls"]="-l \"/tmp/foo bar\""
nor this
parameters["ls"]="-l /tmp/foo\ bar"
works as expected. Similarly, putting quotes around the program call in the loop
$program "${parameters[$program]}"
does not work either, since the two parameters (-l and the path) are interpreted as one parameter.
I found the closest thing to a solution in this post which proposes using multiple separate variables, one for each argument, for the program call. This, however, is not possible in my use case which requires a variable number of arguments for each program - thus my use of the associative array.
Is there any other way to escape the path name?
Best regards Andreas
1 Answer 1
First, create an array with the parameters.
Then, store the array string value (found with declare -p
) at parameters
, and recover and use it as an actual array later on like in:
#!/bin/bash
programs=( "ls" "echo" )
declare -A parameters
arrayTmp=("-l" "/tmp/foo bar")
parameters["ls"]="`declare -p arrayTmp |sed -r "s,[^=]*='(.*)',ドル1,円"`"
parameters["echo"]="Hello"
for program in "${programs[@]}";do
echo "PROGRAM: $program"
declare -a arrayTmp="${parameters[$program]}"
$program "${arrayTmp[@]}"
arrayTmp=()
done
-
Nice - that seems to do the trick. Thank you.Andreas Unterweger– Andreas Unterweger2015年04月27日 07:28:47 +00:00Commented Apr 27, 2015 at 7:28
printf %q
output witheval
). But sounds like an XY problem.bash
. If you do a separate array per 2cd dimension element and!
nameref for each in an indexed array... hacky, and[indexing]
doesnt work butsli:ci:ng
does. But i agree that there is probably a better way to go about this. andreas:bash
is not a db, you know. It's a command interpreter - and not even among the better ones - you really shouldnt be stacking so much state in its env like that. If your problem is your dir tree has spaces and shouldnt - maybe look to removing the spaces.