通过命令行传递数组,以使用getopts()处理

时间:2019-03-15 12:08:51

标签: bash

我尝试将一些参数传递给我的.bash文件。

terminal:

arr=("E1" "E2" "E3")
param1=("foo")
param2=("bar")

现在我要调用execute.bash文件。

execute.bash -a ${arr[@]} -p $param1 -c param2

这是我的文件:

execute.bash:
while getopts ":a:p:c:" opt; do
    case $opt in
        a) ARRAY=${OPTARG};;
        p) PARAM1=${OPTARG};;
        c) PARAM2=${OPTARG};;
        \?) exit "Invalid option -$OPTARG";;
    esac
done

for a in "${ARRAY[@]}"; do
    echo "$a"
done

echo "$PARAM1"
echo "$PARAM2"

但是我的文件只能打印:

E1
foo
bar

我的脚本有什么问题?

3 个答案:

答案 0 :(得分:1)

使用$ {arr [@]}扩展数组中的所有值会将每个值扩展为单独的命令行参数,因此getopt仅将第一个值视为“ -a”选项的参数。

如果使用$ {arr [*]}进行扩展,则所有数组值都将扩展为单个命令行参数,因此getopt可以将数组中的所有值视为“ -a”的单个参数“选项。

还有两个其他问题:您需要在命令行上引用值:

serialize_char

并在getopt处理中使用$ {OPTARG}左右的花括号将其分配为数组:

< execute.bash -a ${arr[@]} -p $param1 -c param2
> execute.bash -a "${arr[*]}" -p $param1 -c $param2

进行这些更改后,我得到以下输出:

< a) ARRAY=${OPTARG};;
> a) ARRAY=(${OPTARG});;

我认为这是您所期望的。

答案 1 :(得分:1)

将数组作为-a标志的参数之一传递时遇到问题。 bash中的数组会在调用实际脚本之前在命令行中扩展。 "${array[@]}"扩展输出用空格分隔的单词

因此,您的脚本以

的形式传递
-a "E1" "E2" "E3" -p foo -c bar

因此,使用getopts()OPTARG的参数-a进行调用时,不会填充不超过第一个值(即仅填充E1)的值。实现此目标的一种方法是使用类型为"${array[*]}"的数组扩展,该数组扩展将字符串与默认的IFS(空白)连接起来,因此-a现在可以看到一个带有数组的单词是串联的,即好像传递为

-a "E1 E2 E3" -p foo -c bar

我强调引述-a的arg会在getopts()收到

#!/usr/bin/env bash

while getopts ":a:p:c:" opt; do
    case $opt in
        a) ARRAY="${OPTARG}";;
        p) PARAM1="${OPTARG}";;
        c) PARAM2="${OPTARG}";;
        \?) exit "Invalid option -$OPTARG";;
    esac
done

# From the received string ARRAY we are basically re-constructing another
# array splitting on the default IFS character which can be iterated over
# as in your input example

read -r -a splitArray <<<"$ARRAY"

for a in "${splitArray[@]}"; do
    echo "$a"
done

echo "$PARAM1"
echo "$PARAM2"

,现在使用args as调用脚本。请注意,您使用的param1param2是变量,但是您的定义似乎将其显示为数组。您的初始化应该看起来像

arr=("E1" "E2" "E3")
param1="foo"
param2="bar"

并调用为

-a "${arr[*]}" -p "$param1" -c "$param2"

请注意,要确保数组arr中的单词尚未包含空格的单词。在这种情况下,如上述那样将它们读回将存在一个问题,那就是将这些单词分开,因为IFSbash处理的性质。在这种情况下,尽管使用不同的分隔符,但在传递数组扩展时请说|#

答案 2 :(得分:0)

如果要导出数组MY_ARRAY,请在调用方使用:

[[ $MY_ARRAY ]] && export A_MY_ARRAY=$(declare -p MY_ARRAY)

...以及在子脚本一侧:

[[ $A_MY_ARRAY =~ ^declare ]] && eval $A_MY_ARRAY

该概念也适用于参数。在呼叫方:

SUB_SCRIPT "$(declare -p MY_ARRAY)"

...以及在子脚本一侧:

[[ $1 =~ ^declare ]] && eval $1

两种解决方案的唯一问题是,变量名在两侧都相同。如果在扩展变量名称之前先替换它,可以更改此名称。