将数组传递给Bash中的函数:意外令牌附近的语法错误`(''

时间:2017-01-21 12:15:48

标签: bash

我正在尝试将字符串数组传递给Bash中的函数,导致“意外令牌附近的语法错误”('“

 #!/usr/bin/env bash                                                                

 function __test() {                                                                
   my_command -c ("a" "b" "c" "d")                                                                                           
 } 

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

您不能让Bash通过引用传递数组,也不能将其复制为单个实体。

有两种方法可以达到预期的效果。

第一个是复制数据

 function __test()
 {
   declare -a array=("a" "b" "c" "d")
   my_command -c "${array[@]}"
 }

my_command()
{
  # Handle options
  [[ "$1" != -c ]] || shift
  # Get your data back in array form by collecting
  # positional parameters in an array
  declare -a array=("$@")
  # Display element at position 2
  echo "${array[2]}"
  # Display all elements
  echo "${array[@]}"
}

如果mycommand是另一种语言的外部程序,那么您将收到数据作为位置参数。

第二种方法是间接方法,只有在同一个Bash脚本中使用数据才能使用,以便变量可以在同一范围内访问。

 function __test()
 {
   declare -a array=("a" "b" "c" "d")
   my_command -c array
 }

my_command()
{
  # Handle options
  [[ "$1" != -c ]] || shift
  varname="$1"
  # Access element at position 2
  x="$varname[2]"
  echo "${!x}"
  # Access all elements
  x="$varname[@]"
  echo "${!x}"
}

您需要确保使用的变量名称不包含任何不需要的数据,否则可能存在风险或代码注入,因此除非变量名完全在您的程序控制之下(不包括用户输入的可能性)在变量名中),你必须找到一种方法来消毒它。

bash的最近变量在变量声明语句(例如-n)中有一个local选项,您可能也想看一下它,但我认为这个选项的部署范围不够广泛除已知配置外,请使用。

请注意,我通常会在函数中声明所有变量local,除非我有特殊原因不这样做,为了清楚起见,上面的代码中已经省略了这一点。

答案 1 :(得分:1)

这是违反语法的行为,

function __test() {                                                                
   my_command -c "a" "b" "c" "d"                                                                                          
} 

将四个字符串传递给my_command()bash中的语法,用于在子shell下执行,这可能不适用于此。

(或)使用数组

function __test() { 
   local myArray=("a" "b" "c" "d" )                                                               
   my_command -c "${myArray[@]}"                                                                                         
} 

您使用数组的想法是正确的,但将整个数组作为${myArray[@]}传递给命令。

您要求getopts来处理此问题,以下是您处理此问题的方法。有两种方法可以做到这一点,

将参数作为单引号字符串“a b c d”

传递
usage() { echo "Usage: $0 [-c args]" 1>&2; exit 1; }

[ $# -eq 0 ] && usage

while getopts ":c:" arg; do
  case $arg in
    c)
      IFS=' ' 
      argsC=($OPTARG)
      ;;

    *) 
      usage; exit 0
      ;;
  esac
done

printf "%s\n" "Number of arguments: ${#argsC[@]}"

现在正在运行,

./script.sh -c "a b c d"
Number of arguments: 4
a
b
c
d

并且要作为多个字符串发送,请将OPTARG值添加到数组中,单独更改getopts部分,

while getopts ":c:" arg; do
  case $arg in
    c)
      argsC+=($OPTARG)
      ;;

    *) 
      usage; exit 0
      ;;
  esac
done

现在运行脚本,

./script.sh -c "a" -c "b" -c "c" -c "d"
Number of arguments: 4
a
b
c
d
du

使用此 [shell check] 网站在语法上验证您的脚本。