简体   繁体   English

如何将数组参数传递给 Bash 脚本

[英]How to pass an array argument to the Bash script

It is surprising me that I do not find the answer after 1 hour search for this.令我惊讶的是,我搜索了 1 小时后没有找到答案。 I would like to pass an array to my script like this:我想像这样将一个数组传递给我的脚本:

test.sh argument1 array argument2

I DO NOT want to put this in another bash script like following:我不想把它放在另一个 bash 脚本中,如下所示:

array=(a b c)
for i in "${array[@]}"
do
  test.sh argument1 $i argument2
done

Bash arrays are not "first class values" -- you can't pass them around like one "thing". Bash数组不是“第一类值” - 你不能像一个“东西”那样传递它们。

Assuming test.sh is a bash script, I would do 假设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[@]}"

And invoke it like 并调用它

test.sh argument1 "${array[@]}" argument2

Have your script arrArg.sh like this: 让你的脚本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[@]}"

Now setup your arrays like this in a shell: 现在在shell中设置这样的数组:

arr=(ab 'x y' 123)
arr2=(a1 'a a' bb cc 'it is one')

And pass arguments like this: 并传递这样的参数:

. ./arrArg.sh "foo" "arr[@]" "bar" "arr2[@]"

Above script will print: 以上脚本将打印:

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

Note: It might appear weird that I am executing script using . ./script 注意:使用脚本执行脚本可能看起来很奇怪. ./script . ./script syntax. . ./script语法。 Note that this is for executing commands of the script in the current shell environment . 请注意,这是用于在当前shell环境中执行脚本的命令。

Q. Why current shell environment and why not a sub shell? 问:为什么当前的shell环境为什么不是子shell?
A. Because bash doesn't export array variables to child processes as documented here by bash author himself 答:因为bash不会将数组变量导出到子进程,如bash作者本人所述

Passing array as argument to script by using alternate separator使用备用分隔符将数组作为参数传递给脚本

Practical sample:实际样本:

Choosing bell character: ascii 0x07 used by C sequence: \a .选择响铃字符:C 序列使用的 ascii 0x07\a

Little preparation: Having a function to prepare variables:小准备:有一个 function 来准备变量:

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:必须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 IFS=我确保IFS varialbe 不会在环境中被修改
  • local -n is a nameref for binding variables. local -n是绑定变量的名称引用
  • ${src[*]} will merge all elements of array to one string by using 1st character of $IFS ${src[*]}将使用$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.当然,我为此使用\a ,这可以(在两侧)替换为从\1\377的任何其他单字节非 null 字符(ascii),而所选字符未在您的数组中使用。

Installation and remote execution安装和远程执行

The function mergeArray could be installed into your .bashrc for sample or in any file to be sourced before you run your script. function mergeArray可以安装到您的.bashrc中以供示例或在您运行脚本之前获取的任何文件中。

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 <<eoRemote
    /path/to/script  "$var1" "$mergedArray" "This seem nice, isnt't it?"
eoRemote

On my remote host, this produce:在我的远程主机上,这会产生:

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?"

You can write your array to a file, then source the file in your script. 您可以将数组写入文件,然后在脚本中获取文件。 eg: 例如:

array.sh array.sh

array=(a b c)

test.sh test.sh

source $2
...

Run the test.sh script: 运行test.sh脚本:

./test.sh argument1 array.sh argument3

If the values have no spaces (ie they are urls, identifiers, numbers, etc) you can do this:如果值没有空格(即它们是 url、标识符、数字等),您可以这样做:

ARRAY=(one two three)
test.sh argument1 "${ARRAY[*]}" argument3

which is the same as:这与:

test.sh argument1 "one two three" argument3

And in test.sh you do:test.sh你做:

ARG1="$1"
ARRAY=($2) # Note that we don't add quotes
ARG3="$3"

If values have spaces I would go for glenn jackman's answer and simplify it by passing the array as the last argument:如果值有空格,我会选择glenn jackman 的答案并通过将数组作为最后一个参数传递来简化它:

ARRAY=("the first" "the second" "the third")
test.sh argument1 argument2 "${ARRAY[@]}"

which is the same as:这与:

test.sh argument1 argument2 "the first" "the second" "the third"

And in test.sh do:test.sh做:

ARG1="$1"; shift
ARG2="$1"; shift
ARRAY=("$@")

The best solution that I'm found here我在这里找到的最佳解决方案

f() {
    declare -a argAry1=("${!1}")
    echo "${argAry1[@]}"
    # ...
}

arr1=(
    "a"
    "b"
)
f arr1[@] arr2[@] arg2

if the length of your array is not too long, you can convert the array to a string which joining with ','如果你的数组长度不是太长,你可以将数组转换为字符串,用','连接

file1.sh文件1.sh

s=${1}
arr=(`echo ${s} | tr ',' ' '`)  # then we can convert str to arr

file2.sh文件2.sh

a="1,2,3,4"
sh file1.sh ${a} 

If this is your command: 如果这是你的命令:

test.sh argument1 ${array[*]} argument2

You can read the array into test.sh like this: 您可以将数组读入test.sh,如下所示:

arg1=$1
arg2=${2[*]}
arg3=$3

It will complain at you ("bad substitution"), but will work. 它会向你抱怨(“糟糕的替代”),但会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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