[英]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.