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!"
}
:-)