【问题标题】:Validate bash script arguments验证 bash 脚本参数
【发布时间】:2019-11-16 21:57:50
【问题描述】:

我正在尝试做这样的事情来制作脚本以在备份失败时执行备份。我将环境作为脚本的参数。

我不确定如何做的一件事是我想验证 $1 以仅包含一些预定义的值。预定义的值应该类似于 tst、prd、qa、rpt。任何人?

#!/bin/bash
ENVIRONMENT=$1 
BACKUPDATE=$(date +"%d_%m_%Y")
BACKUPFILE="$ENVIRONMENT".backup."$BACKUPDATE".tar.gz

if [ $1 ==  "" ] 
 then
 echo "No environment specified"
 exit
elif [ -f "$BACKUPFILE" ]; then
   echo "The file '$BACKUPFILE' exists."
else
   echo "The file '$BACKUPFILE' in not found."
   exec touch "$BACKUPFILE"
fi

【问题讨论】:

  • 第一次测试的单行:[[ -z "$1" ]] && echo "No environment specified" && exit 1。你不需要exec touchtouch 一个人就够了。
  • @Matthieu 较短的单行:: ${1:?No environment specified}
  • @chepner 我知道周围有东西,谢谢! (另见stackoverflow.com/questions/8889302/…
  • [ "$1" = "" ],或者只是[ -z "$1" ]。总是引用你的扩展,不要使用==the POSIX specification for test 中没有标准化。

标签: bash


【解决方案1】:

你可以使用case:

case "$1" in
    tst) echo "Backing up Test style" ;;
    prd)
        echo "Production backup"
        /etc/init.d/myservice stop
        tar czf ...
        /etc/init.d/myservice start
        ;;
    qa) echo "Quality skipped" ;;
    rpt)
        echo "Different type of backup"
        echo "This could be another processing"
        ...
        ;;
    *)
        echo "Unknown backup type"
        exit 2
        ;;
esac

注意结束每个案例的双 ;;,以及 convenient use of pattern matching

编辑:按照您的评论和@CharlesDuffy 的建议,如果您想在一个数组中包含所有有效选项并针对其中的 any 测试您的值(因此对于 所有有效值),您可以使用associative array

declare -A valids=(["tst"]=1 ["prd"]=1 ["qa"]=1 ["rpt"]=1)
if [[ -z ${valids[$1]} ]] ; then
    echo "Invalid parameter value"
    # Any other processing here ...
    exit 1
fi
# Here your parameter is valid, proceed with processing ...

这通过将值(此处为 1 但在这种情况下可能是其他任何值)分配给 每个 有效参数来实现。所以任何 invalid 参数都将为空,-z 测试将触发。

功劳归他所有。

【讨论】:

  • @runegjo 您可以使用选项列表编辑您的问题,我们将向您展示一些示例 :) 每个 case 表达式对应于一个可能的选择,您将相应的代码放在 @ 987654332@ 和;;
  • 顺便说一句,请注意,TLDP,尤其是 ABS,因过时的信息和展示不良做法的示例而臭名昭著。 Wooledge BashGuide 专门编写为没有这些故障的替代品。 ABS 没有列在stackoverflow.com/tags/bash/info 的“书籍和资源”部分是有原因的;请考虑链接到官方手册、bash-hackers' wiki 或指南。
  • @CharlesDuffy,感谢您提供有关来源的宝贵信息。我用 bash-hackers 的 wiki 链接编辑了我的答案,我在很久以前使用过很多次。
  • @runegjo 我在编辑中添加了 Charles Duffy 的评论。看看它是否更适合您。
  • @CharlesDuffy 我用你的评论来编辑我的答案。如果你自己回答,我会回滚那个编辑。
【解决方案2】:

根据您有多少不同的值,case 语句呢?它甚至允许通配符。

case $1 in
  (John)   printf "Likes Yoko\n";;
  (Paul)   printf "Likes to write songs\n";;
  (George) printf "Harrison\n";;
  (Ringo)  printf "Da drumma\n";;
  (*)      printf "Management, perhaps?\n";;
esac

另一方面,如果可以,您应该避免使用不可移植的 bashism,例如 [[ 测试运算符(如果可以,请使用 [,例如 if [ "$1" = "John" ]; then ...; fi。)

【讨论】:

  • @runegjo 最终由你决定:[[ ]] 更灵活,如果你知道bash 在你的机器上可用(通常是这样),则可以安全使用。
  • @Matthieu 是的,初始 ( 是可选的。我总是使用它,因为我(和 vi)喜欢匹配的括号。
  • @Jens, ...bashisms? [[ 是几乎所有扩展外壳都采用的 ksh-ism,而且有充分的理由;使解析器识别[[ 语法允许[ 无法执行的功能(如全局匹配)和安全功能(如完全确定地识别语法和数据之间的差异;而[ 需要具有标记为过时的功能以避免歧义)。
  • @runegjo,针对 associative 数组(一些其他语言称为映射或哈希的数据结构),简单而快速。对于常规的数字索引数组,您需要循环,这样效率会低得多。
  • declare -A validValues=( ["validOne"]=1 ["validTwo"]=1 ["whatever"]=1 ); if [[ ${validValues[$myValue]} ]]; then echo "$myValue is listed as valid"; fi
猜你喜欢
  • 1970-01-01
  • 2021-04-29
  • 2022-12-02
  • 2021-03-05
  • 2020-08-31
  • 2010-10-24
  • 2013-08-02
  • 2013-04-20
相关资源
最近更新 更多