简体   繁体   中英

Passing and Parsing an Array from one shell script to another

Due to the limitation of 9 parameters in a script, my objective is to pass about 30 strings bundled in an array from calling script (scriptA) to called script (scriptB).

My scriptA looks something like this...

#!/bin/bash
declare -a arr=( ab "c d" 123 "string with spaces" 456 )
. ./scriptB.sh "Task Name" "${arr[@]}"

My scriptB looks something like this...

#!/bin/bash
arg1="$1"
shift
arg2=("$@")
read -a arr1 <<< "$@"
j=0
for i in "${arr1[@]}"; do
#echo ${arr1[j]}
((j++))
case "$j" in
"1")
param1="${i//(}"
echo "$j=$param1"
;;
"2")
param2="${i}"
echo "$j=$param2"
;;
"3")
param3="${i}"
echo "$j=$param3"
;;
"4")
param4="${i}"
echo "$j=$param4"
;;
"5")
param5="${i//)}"
echo "$j=$param5"
;;
esac
done

OUTPUT:

1=ab
2=c
3=d
4=123
5=string

Problem:

1. I see parenthesis ( and ) gets added to the string which I have to strip them out
2. I see an array element (with spaces) though quoted under double quotes get to interpreted as separate elements by spaces.

read -a arr1 <<< "$@"

is wrong. The "$@" here is equal to "$*" , and then read will split the input on whitespaces (spaces, tabs and newlines) and also interpret \ slashes and assign the result to array arr1 . Remember to use read -r .

Do:

arr1=("$@")

to assign to an array. Then you could print with:

for ((i=1;i<${#arr1};++i)); do 
   printf "%d=%s\n" "$i" "${arr1[$i]}"
done

of 9 parameters in a script, my objective is to pass about 30 strings bundled in an array from calling script (scriptA)

Ok. But "${arr[@]}" is passing multiple arguments anyway. If you want to pass array as string, pass it as a string (note that eval is evil ):

arr=( ab "c d" 123 "string with spaces" 456 )
./scriptB.sh "Task Name" "$(declare -p arr)"
# Then inside scriptB.sh, re-evaulate parameter 2:
eval "$2" # assigns to arr

Note that the scriptB.sh is sourced in your example, so passing arguments.... makes no sense anyway.

I see an array element (with spaces) though quoted under double quotes get to interpreted as separate elements by spaces

Yes, because you interpreted the content with read , which splits the input on characters in IFS , which by default is set to space, tab and newline. You could print arguments on separate lines and change IFS accordingly:

IFS=$'\n' read -r -a arr1 < <(printf "%s\n" "$@")

or even use a zero terminated string:

mapfile -t -d '' arr1 < <(printf "%s\0" "$@")

but those are just fancy and useless ways of writing arr1=("$@") .

Note that in your code snipped, arg2 is an array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM