2

I've got the following shell script:

#!/usr/bin/env bash
PARAMS=( arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 )
[ $# -lt ${#PARAMS[@]} ] && { echo "Usage: $0 ${PARAMS[@]}"; exit 1; }
DATA=$(printf "%s=%s&" ${PARAMS[@]} $@)
echo curl "http://example.com/api/?${DATA%?}"

which aims at taking n-number of parameters and associate them with values read from the arguments.

So when I run:

./curl_params.sh 1 2 3 4 5 6 7 8 9

I expect the format to be:

curl http://example.com/api/?arg1=1&arg2=2&arg3=3&arg4=4&arg5=5&arg6=6&arg7=7&arg8=8&arg9=9

but instead, I've got:

curl http://example.com/api/?arg1=arg2&arg3=arg4&arg5=arg6&arg7=arg8&arg9=1&2=3&4=5&6=7&8=9

I understand that I need to combine ${PARAMS[@]} with $@, so the values are merged.

Is there any Bash syntax that I can use to transpose/map the argument names with corresponding values?

To clarify, the names of the arguments may change.

2

paste + printf solution:

#!/usr/bin/env bash
PARAMS=( arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 )
[ $# -lt ${#PARAMS[@]} ] && { echo "Usage: $0 ${PARAMS[@]}"; exit 1; }
data=$(paste -sd'&' <(paste -d= <(printf "%s\n" "${PARAMS[@]}") <(printf "%s\n" "$@")))
echo curl "http://example.com/api/?${data}"

Test:

./curl_params.sh 1 2 3 4 5 6 7 8 9
curl http://example.com/api/?arg1=1&arg2=2&arg3=3&arg4=4&arg5=5&arg6=6&arg7=7&arg8=8&arg9=9
2

I would store $@ in an array, then iterate over the indices: consider this bash session:

$ set -- a b c d e f g h i
$ args=( "$@" )
$ params=( arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 )
$ declare -p params args
declare -a params='([0]="arg1" [1]="arg2" [2]="arg3" [3]="arg4" [4]="arg5" [5]="arg6" [6]="arg7" [7]="arg8" [8]="arg9")'
declare -a args='([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [7]="h" [8]="i")'
$ for ((i=0; i<$#; i++)); do echo "${params[i]}=${args[i]}"; done
arg1=a
arg2=b
arg3=c
arg4=d
arg5=e
arg6=f
arg7=g
arg8=h
arg9=i
$ for ((i=0; i<$#; i++)); do echo "${params[i]}=${args[i]}"; done | paste -s -d'&'
arg1=a&arg2=b&arg3=c&arg4=d&arg5=e&arg6=f&arg7=g&arg8=h&arg9=i

However, bash can't handle

data=$( for ((i=0; i<$#; i++)); do echo "${params[i]}=${args[i]}"; done | paste -s -d'&' )

Apparently bash can't handle all the parentheses properly: In a script I get this error:

bash: unexpected EOF while looking for matching `)'
bash: syntax error: unexpected end of file

So you can use a different loop:

data=$(
    let i=0
    while [[ $i -lt $# ]]; do
        echo "${params[i]}=${args[i]}"
        let i++
    done | paste -s -d'&'
)
echo "$data"

Note, don't use ALL_CAPS_VARNAMES, leave those as reserved by the shell.


If your PARAMS is always "arg" followed by a number, you don't need to store "$@" in an array, you can refer to them with an indirect variable:

data=$(
    let i=1                          # note, starts at 1
    while [[ $i -le $# ]]; do        # and uses "-le"
        echo "arg${i}=${!i}"         # with ${!i} to get the positional param
        let i++
    done | paste -s -d'&'
)
echo "$data"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.