【问题标题】:How to write a bash script that takes optional input arguments?如何编写带有可选输入参数的 bash 脚本?
【发布时间】:2012-03-09 02:54:58
【问题描述】:

我希望我的脚本能够接受可选输入,

例如目前我的脚本是

#!/bin/bash
somecommand foo

但我想说:

#!/bin/bash
somecommand  [ if $1 exists, $1, else, foo ]

【问题讨论】:

标签: bash arguments parameter-passing


【解决方案1】:

您可以使用默认值语法:

somecommand ${1:-foo}

以上将,如Bash Reference Manual - 3.5.3 Shell Parameter Expansion [emphasis mine] 中所述:

如果参数未设置或为空,则替换单词的扩展。否则,参数的值被替换。

如果您只想在参数未设置的情况下替换默认值(但如果它为空则不替换,例如,如果它是空字符串则不替换),请改用以下语法:

somecommand ${1-foo}

再次来自Bash Reference Manual - 3.5.3 Shell Parameter Expansion

省略冒号会导致仅对未设置的参数进行测试。换句话说,如果包含冒号,则运算符会测试两个参数的存在以及它的值是否不为空;如果省略冒号,则运算符仅测试存在性。

【讨论】:

  • 请注意上述命令之间的语义差异,“return foo if $1 is unset or an empty string”和${1-foo}, “return @ 987654330@ 如果$1 未设置”。
  • 您能解释一下为什么会这样吗?具体来说,':' 和 '-' 的功能/用途是什么?
  • @jwein001:在上面提交的答案中,如果变量未定义,则使用替换运算符返回默认值。具体来说,逻辑是“如果 $1 存在且不为空,则返回其值;否则,返回 foo”。冒号是可选的。如果省略,则将“存在且不为空”更改为仅“存在”。减号指定返回 foo 而不将 $1 设置为 'foo'。替换运算符是扩展运算符的子类。请参阅 Robbins 和 Beebe 的 Classic Shell Scripting [O'Reilly] (shop.oreilly.com/product/9780596005955.do) 的第 6.1.2.1 节
  • @Jubbles 或者如果您不想购买整本书作为简单的参考...tldp.org/LDP/abs/html/parameter-substitution.html
  • 这个答案会更好,如果它展示了如何让默认值成为运行命令的结果,就像@hagen 所做的那样(尽管这个答案不优雅)。
【解决方案2】:

您可以像这样为变量设置默认值:

somecommand.sh

#!/usr/bin/env bash

ARG1=${1:-foo}
ARG2=${2:-bar}
ARG3=${3:-1}
ARG4=${4:-$(date)}

echo "$ARG1"
echo "$ARG2"
echo "$ARG3"
echo "$ARG4"

以下是其工作原理的一些示例:

$ ./somecommand.sh
foo
bar
1
Thu Mar 29 10:03:20 ADT 2018

$ ./somecommand.sh ez
ez
bar
1
Thu Mar 29 10:03:40 ADT 2018

$ ./somecommand.sh able was i
able
was
i
Thu Mar 29 10:03:54 ADT 2018

$ ./somecommand.sh "able was i"
able was i
bar
1
Thu Mar 29 10:04:01 ADT 2018

$ ./somecommand.sh "able was i" super
able was i
super
1
Thu Mar 29 10:04:10 ADT 2018

$ ./somecommand.sh "" "super duper"
foo
super duper
1
Thu Mar 29 10:05:04 ADT 2018

$ ./somecommand.sh "" "super duper" hi you
foo
super duper
hi
you

【讨论】:

  • 啊,好的。 - 让我很困惑(被否定了吗?)。
  • 不——这只是 bash 完成任务的一种奇怪方式。我将添加更多示例来澄清这一点...谢谢!
【解决方案3】:
if [ ! -z $1 ] 
then 
    : # $1 was given
else
    : # $1 was not given
fi

【讨论】:

  • 从技术上讲,如果您传入一个可能算作参数的空字符串 '',但您的检查将错过它。在这种情况下,$# 会说明给出了多少个参数
  • -n! -z 相同。
  • 我使用-n! -z 得到不同的结果,所以我想说这里不是这种情况。
  • 因为你没有引用变量,[ -n $1 ] 永远是真的。如果你使用 bash,[[ -n $1 ]] 的行为会如你所愿,否则你必须引用 [ -n "$1" ]
  • 对于像我这样的人:忘记代码中的“:”,它不是必需的,用你的真实命令替换它!
【解决方案4】:

您可以使用$#检查参数的数量

#!/bin/bash
if [ $# -ge 1 ]
then
    $1
else
    foo
fi

【讨论】:

    【解决方案5】:

    请不要忘记,如果它的变量 $1 .. $n 您需要写入常规变量才能使用替换

    #!/bin/bash
    NOW=$1
    echo  ${NOW:-$(date +"%Y-%m-%d")}
    

    【讨论】:

    • Brad 上面的answer 证明了参数变量也可以在没有中间变量的情况下被替换。
    • +1 用于注意使用 date 等命令作为默认值而不是固定值的方式。这也是可能的:DAY=${1:-$(date +%F -d "yesterday")}
    【解决方案6】:

    这允许可选第一个参数的默认值,并保留多个参数。

     > cat mosh.sh
       set -- ${1:-xyz} ${@:2:$#} ; echo $*    
     > mosh.sh
       xyz
     > mosh.sh  1 2 3
       1 2 3 
    

    【讨论】:

      【解决方案7】:

      对于可选的多个参数,类似于ls 命令,它可以接收一个或多个文件,或者默认列出当前目录中的所有内容:

      if [ $# -ge 1 ]
      then
          files="$@"
      else
          files=*
      fi
      for f in $files
      do
          echo "found $f"
      done
      

      对于路径中有空格的文件不能正常工作,唉。还没想好怎么做。

      【讨论】:

        【解决方案8】:

        可以使用变量替换来用固定值或命令(如date)替换参数。到目前为止的答案都集中在固定值上,但这是我用来将日期设为可选参数的原因:

        ~$ sh co.sh
        2017-01-05
        
        ~$ sh co.sh 2017-01-04
        2017-01-04
        
        ~$ cat co.sh
        
        DAY=${1:-$(date +%F -d "yesterday")}
        echo $DAY
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多