[英]How to pass an array argument to the Bash script
令我驚訝的是,我搜索了 1 小時后沒有找到答案。 我想像這樣將一個數組傳遞給我的腳本:
test.sh argument1 array argument2
我不想把它放在另一個 bash 腳本中,如下所示:
array=(a b c)
for i in "${array[@]}"
do
test.sh argument1 $i argument2
done
Bash數組不是“第一類值” - 你不能像一個“東西”那樣傳遞它們。
假設test.sh
是一個bash腳本,我會這樣做
#!/bin/bash
arg1=$1; shift
array=( "$@" )
last_idx=$(( ${#array[@]} - 1 ))
arg2=${array[$last_idx]}
unset array[$last_idx]
echo "arg1=$arg1"
echo "arg2=$arg2"
echo "array contains:"
printf "%s\n" "${array[@]}"
並調用它
test.sh argument1 "${array[@]}" argument2
讓你的腳本arrArg.sh
像這樣:
#!/bin/bash
arg1="$1"
arg2=("${!2}")
arg3="$3"
arg4=("${!4}")
echo "arg1=$arg1"
echo "arg2 array=${arg2[@]}"
echo "arg2 #elem=${#arg2[@]}"
echo "arg3=$arg3"
echo "arg4 array=${arg4[@]}"
echo "arg4 #elem=${#arg4[@]}"
現在在shell中設置這樣的數組:
arr=(ab 'x y' 123)
arr2=(a1 'a a' bb cc 'it is one')
並傳遞這樣的參數:
. ./arrArg.sh "foo" "arr[@]" "bar" "arr2[@]"
以上腳本將打印:
arg1=foo
arg2 array=ab x y 123
arg2 #elem=3
arg3=bar
arg4 array=a1 a a bb cc it is one
arg4 #elem=5
注意:使用腳本執行腳本可能看起來很奇怪. ./script
. ./script
語法。 請注意,這是用於在當前shell環境中執行腳本的命令。
問:為什么當前的shell環境為什么不是子shell?
答:因為bash不會將數組變量導出到子進程,如bash作者本人所述
選擇響鈴字符:C 序列使用的 ascii 0x07
: \a
。
小准備:有一個 function 來准備變量:
mergeArray() {
local IFS=$'\a'
local -n src=$1 tgt=$2
tgt=${src[*]}
}
然后腳本可能如下所示:
#!/bin/bash
arg1="$1"
IFS=$'\a' read -ra arg2 <<<"$2"
arg3="$3"
declare -p arg{1,2,3}
在實踐中:
var1=Hello var2=(foo bar baz) var3=world.
mergeArray var2 mvar2
bash script "$var1" "$mvar2" "$var3"
必須output:
declare -- arg1="Hello"
declare -a arg2=([0]="foo" [1]="bar" [2]="baz")
declare -- arg3="world."
local IFS=
我確保IFS
varialbe 不會在環境中被修改local -n
是綁定變量的名稱引用。${src[*]}
將使用$IFS
的第一個字符將數組的所有元素合並為一個字符串\a
,這可以(在兩側)替換為從\1
到\377
的任何其他單字節非 null 字符(ascii),而所選字符未在您的數組中使用。 function mergeArray
可以安裝到您的.bashrc
中以供示例或在您運行腳本之前獲取的任何文件中。
一旦完成,腳本本身甚至可以遠程定位。 然后通過相同的命令運行:
ssh user@remote /path/to/script "$var1" "$mvar2" "$var3"
但對於更強大的遠程執行,我更喜歡:
myArray=("foo bar baz" 'alice bob charlie' 'strawberry raspberry')
mergeArray myArray mergedArray
var1="Hello world!"
ssh user@remote /bin/bash <<eoRemote
/path/to/script "$var1" "$mergedArray" "This seem nice, isnt't it?"
eoRemote
在我的遠程主機上,這會產生:
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?"
您可以將數組寫入文件,然后在腳本中獲取文件。 例如:
array.sh
array=(a b c)
test.sh
source $2
...
運行test.sh腳本:
./test.sh argument1 array.sh argument3
如果值沒有空格(即它們是 url、標識符、數字等),您可以這樣做:
ARRAY=(one two three)
test.sh argument1 "${ARRAY[*]}" argument3
這與:
test.sh argument1 "one two three" argument3
在test.sh
你做:
ARG1="$1"
ARRAY=($2) # Note that we don't add quotes
ARG3="$3"
如果值有空格,我會選擇glenn jackman 的答案並通過將數組作為最后一個參數傳遞來簡化它:
ARRAY=("the first" "the second" "the third")
test.sh argument1 argument2 "${ARRAY[@]}"
這與:
test.sh argument1 argument2 "the first" "the second" "the third"
在test.sh
做:
ARG1="$1"; shift
ARG2="$1"; shift
ARRAY=("$@")
我在這里找到的最佳解決方案
f() {
declare -a argAry1=("${!1}")
echo "${argAry1[@]}"
# ...
}
arr1=(
"a"
"b"
)
f arr1[@] arr2[@] arg2
如果你的數組長度不是太長,你可以將數組轉換為字符串,用','連接
文件1.sh
s=${1}
arr=(`echo ${s} | tr ',' ' '`) # then we can convert str to arr
文件2.sh
a="1,2,3,4"
sh file1.sh ${a}
如果這是你的命令:
test.sh argument1 ${array[*]} argument2
您可以將數組讀入test.sh,如下所示:
arg1=$1
arg2=${2[*]}
arg3=$3
它會向你抱怨(“糟糕的替代”),但會起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.