Passing array as argument to script by using alternate separator
And passing array as argument to remote script by using alternate separator
Practical sample:
Choosing bell character: ascii 0x07 used by C sequence: \a.
Little preparation: Having a function to prepare variables:
mergeArray() {
local IFS=$'\a'
local -n src=$1 tgt=$2
tgt=${src[*]}
}
Then the script could look like:
#!/bin/bash
arg1="$1"
IFS=$'\a' read -ra arg2 <<<"$2"
arg3="$3"
declare -p arg{1,2,3}
In practice:
var1=Hello var2=(foo bar baz) var3=world.
mergeArray var2 mvar2
bash script "$var1" "$mvar2" "$var3"
must output:
declare -- arg1="Hello"
declare -a arg2=([0]="foo" [1]="bar" [2]="baz")
declare -- arg3="world."
Explanations
- by using
local IFS= I ensure IFS varialbe won't be modified in environment
local -n is a nameref for binding variables.
${src[*]} will merge all elements of array to one string by using 1st character of $IFS
- Of course, I use
\a for this, this could replaced (on both side) by any other single byte non null character (ascii) from \1 to \377, while choosed character is not used in your array.
Installation and remote execution
The function mergeArray could be installed into your .bashrc file or into a separated file to be sourced before you run your script.
Once done, the script himself could even be located remotely. then run by same command:
ssh user@remote /path/to/script "$var1" "$mvar2" "$var3"
But for more robust remote execution I prefer:
myArray=("foo bar baz" 'alice bob charlie' 'strawberry raspberry')
mergeArray myArray mergedArray
var1="Hello world!"
ssh user@remote /bin/bash -s <<eoRemote
/path/to/script "$var1" "$mergedArray" "This seem nice, isnt't it?"
eoRemote
From my remote host, I will read:
declare -- arg1="Hello world!"
declare -a arg2=([0]="foo bar baz" [1]="alice bob charlie" [2]="strawberry raspberry")
declare -- arg3="This seem nice, isnt't it?"
( Notice the mixing of single quotes and double quotes!! ;-)
Passing Associative arrays as argument to remote bash via ssh
Things become a little stronger!
mergeArray () {
local -n _srce=${1?Source var missing.} _trgt=${2?Target var missing.}
local _tvar
IFS=\ read _ _tvar _ <<< "${_srce@A}"
case ${_tvar#-} in
*a*) local IFS=$'\a'; _trgt=${_srce[*]} ;;
*A*) _trgt=''
for _tvar in "${!_srce[@]}" ;do
printf -v _tvar '%s\a%s\a' "$_tvar" "${_srce[$_tvar]}"
_trgt+="$_tvar"
done
_trgt=${_trgt%$'\a'} ;;
* ) printf >&2 '%s ERROR: Variable "%s" is not an array.\n' \
$FUNCNAME "$1"
return 1 ;;
esac
}
Then parsing args in script will become:
#!/bin/bash
arg1=${1}
IFS=$'\a' read -ra arg2 <<<"$2"
IFS=$'\a' read -ra _tmpvar <<<"$3"
printf -v _tmpvar '[%s]="%s" ' "${_tmpvar[@]//\"/\\\"}"
declare -A arg3="($_tmpvar)"
arg4=$4
declare -p arg{1,2,3,4}
In action:
var1="Hello world!"
myArray=("foo bar baz" 'alice bob charlie' 'strawberry raspberry')
declare -A myAArray='([Full name]="John Doo" [Birth date]="1970/01/02 12:34:56"
[Status]="Maried" [Title]="Chief")'
mergeArray myArray mergedArray
mergeArray myAArray mergedAArray
ssh user@remote /bin/bash -s <<eoRemote
/path/to/script "$var1" "$mergedArray" "$mergedAArray" "Still seem nice, isn't it?"
eoRemote
declare -- arg1="Hello world!"
declare -a arg2=([0]="foo bar baz" [1]="alice bob charlie" [2]="strawberry raspberry")
declare -A arg3=(["Birth date"]="1970/01/02 12:34:56" [Title]="Chief" [Status]="Maried" ["Full name"]="John Doo" )
declare -- arg4="Sill seem nice, isn't it?"
Passing complex variables as arguments over ssh
And for holding double-quotes in addition to already supported single-guotes, spaces and others,
remplace $varNAme by ${varName//\"/\\\"}:
var1="Hello world!"
myArray=("foo bar baz" 'alice bob charlie' 'strawberry raspberry')
declare -A myAArray='([Full name]="John Doo" [Birth date]="1970/01/02 12:34:56"
[Status]="Maried")'
myAArray[Title]="Chief's pain sufferer"
myAArray[datas]='{ "height": "5.5 feet", "weight":"142 pounds",'
myAArray[datas]+=$' "phrase": "Let\'s go!" }'
mergeArray myArray mergedArray
mergeArray myAArray mergedAArray
ssh user@remote /bin/bash -s <<eoRemote
/path/to/script "${var1//\"/\\\"}" "${mergedArray//\"/\\\"}" \
"${mergedAArray//\"/\\\"}" "This still seem nice, isn't it?"
eoRemote
declare -- arg1="Hello world!"
declare -a arg2=([0]="foo bar baz" [1]="alice bob charlie" [2]="strawberry raspberry")
declare -A arg3=([Title]="Chief's pain sufferer" [Status]="Maried" ["Birth date"]="1970/01/02 12:34:56" ["Full name"]="John Doo" [datas]="{ \"height\": \"5.5 feet\", \"weight\":\"142 pounds\", \"phrase\": \"Let's go!\" }" )
declare -- arg4="This still seem nice, isn't it?"
Or after some foldering:
declare -- arg1="Hello world!"
declare -a arg2=([0]="foo bar baz" [1]="alice bob charlie"
[2]="strawberry raspberry" )
declare -A arg3=([Title]="Chief's pain sufferer" [Status]="Maried"
["Birth date"]="1970/01/02 12:34:56" ["Full name"]="John Doo"
[datas]="{ \"height\": \"5.5 feet\", \"weight\":\"142 pounds\",
\"phrase\": \"Let's go!\" }" )
declare -- arg4="This still seem nice, isn't it?"
( By adding: jq <<<${arg3[datas]} at end of my script, I see:
{
"height": "5.5 feet",
"weight": "142 pounds",
"phrase": "Let's go!"
}
:-)