关联数组

关联数组

我想操作用户输入后从数组中选择的变量的扩展值。这就是我的意思:

$ ./myscript.sh url2


#!/bin/bash

array=(Sigil wp2epub csskit)

Sigil       =   "https://github.com/Sigil-Ebook/Sigil.git"
csskit      =   "https://github.com/mattharrison/epub-css-starter-kit.git"
wp2epub     =   "https://github.com/mrallen1/wp2md.git"

if [ -z $1 ]; then
  echo "This script needs at least one parameter!"
  exit 1
fi

if [ $1 = Sigil ]; then
  ans=$Sigil # expanded
elif [ $1 = csskit ]; then
  ans=$csskit # expanded
elif [ $1 = wp2epub ]; then
  ans=$wp2epub # expanded
else
  echo "Please inform one of \
        Sigil, csskit or wp2epub!"
fi

git clone $ans

解释:

该脚本检查用户输入 ($1),将其与可能变量的数组进行比较,如果找到,它将检索该变量的扩展值作为答案,然后使用扩展值(而不是变量名称)。

我已经尝试了好几天了,但我有限的 bash 脚本编写能力还不够......

提前致谢。


根据 @terdon 请求:我希望用户告知数组中变量的名称,这将是人类友好的。

这些变量实际上是需要从github(git克隆)获取然后重新编译和重新安装的包的名称。

实际用法是:

$ ./update.sh Sigil # Sigil is one of the variables

答案1

使用关联数组:

#!/bin/bash

declare -A url
url=( [url1]="http://www.google.com"
      [url2]="http://www.yahoo.com"
      [url3]="http://www.bing.com"
    )

if [[ -z $1 ]] ; then
    echo "This script needs at least one parameter!"
    exit 1
elif [[ -z ${url[$1]} ]] ; then
    echo 'Unknown option'
    exit 1
fi

echo "Let's search ${url[$1]}."

答案2

在您提供的脚本中:$1包含选项的名称,并且 an$array包含选项的值。要根据您的请求在扩展的变量中获取结果$ans,有几个选项:

评估

eval:将 $1 展开为Sigil例如,并赋值$Sigil给 ans:

eval ans\=\"\$\{"$1"\}\"

然而,这假设这$1是一个变量的单字标签。如果输入有其他内容,则可能会被 eval 评估。更强大的 eval 解决方案是使用${array[i]}替代方案,因为数组的内容由脚本控制。

间接

bash 中一个相近的惯用语是${!1}.这就是获取 var 所指向的值$1,这正是我们所需要的。再次,更稳健地使用(一旦找到${array[i]}匹配:$array[i]

a="array[i]"; ans="${!a}"

关联数组

但是,如果我们对数组键和数组值使用关联数组,则所有 eval 和间接寻址问题都可以避免。

然后很容易找到正确的值,如果数组有值,那么它就是有效值。如果数组中没有某个键的值,则该键无效。

基于这个概念的完整脚本可能如下所示:

#!/bin/bash

[ $# -lt 1 ] && {  echo "This script needs at least one parameter!"; exit 1; }

declare -A a
    a=(
    [Sigil]="https://github.com/Sigil-Ebook/Sigil.git"
    [wp2epub]="https://github.com/mattharrison/epub-css-starter-kit.git"
    [csskit]="https://github.com/mrallen1/wp2md.git"
    )


### Process an error while informing of options.
for    val in "${!a[@]}"
do     d=$d${d:+", "}$last
       last=$val
done
d="Please inform one of $d or $last"
SayError(){ echo "$d" >&2; exit 1; }



### Process a valid command execution.
ExecCmd(){ git clone "$ans"; }



### Process all arguments of script.
for    arg
do     unset ans                          ### unset result variable.
       printf -v ans '%s' "${a[$arg]}"    ### Assign result to "$ans"
       ${ans:+:} SayError                 ### If "$ans" is empty, process error.
       ${ans:+false} || ExecCmd           ### With valid "$ans" execute command.
done

可以更改函数 SayError 以消除exit 1,脚本仍将处理所有参数,并对无效值发出警告。

答案3

arr=($url1 $url2 $url3)

for i in ${arr[@]}; do
  if [[ $i == $1 ]] ;then
    ans=$i
    break
  fi
done

相关内容