如何使选项接受任意数量的参数

时间:2018-05-24 19:49:47

标签: shell

我正在尝试编写一个shell脚本,其中包含在每次运行中使用不同数量值的选​​项,例如

运行1:

./myscript --input <file1> <file2> --output <folder1>

运行2:

./myscript --input <file1> <file2> <file3> --output <folder1> <folder2>

我尝试使用getopts如下:

while getopts ":i:o:" opt; do
  case $opt in
  i)
    echo "treatment files are: $OPTARG" >&2
    infiles="${OPTARG}"
  ;;
  o)
    echo "control files are: $OPTARG" >&2
    outdir="${OPTARG}"
  ;;
  \?)
    echo "Invalid option: -$OPTARG" >&2
    exit 1
  ;;
  :)
    echo "Option -$OPTARG requires an argument." >&2
    exit 1
  ;;
  esac
done

然而,我发现为&#34; -i&#34;输入可变数量的值的唯一方法选项是引用(&#34; file1 file2&#34;),这会阻止我/用户使用命令行的自动完成功能来帮助生成文件路径。此选项似乎也不允许我使用&#34; - 输入&#34;语法来传递选项。

有人可以帮忙吗?

非常感谢。

1 个答案:

答案 0 :(得分:3)

这里有两个问题。其中一个是“如何在我的shell脚本中实现长选项?”,其中有良好的阅读here

另一个问题是,“我如何选择接受任意数量的参数?”答案主要是“你没有”。通常最干净的解决方案是让您的脚本多次接受该选项,如:

./myscript -i <file1> -i <file2> -i <file3>

通过附加到Bash数组可以相对容易地处理,如:

infiles=()
while getopts ":i:o:" opt; do
  case $opt in
  i)
    infiles+=("${OPTARG}")
  ;;
  esac
done

稍后您可以迭代这些值:

for inputfile in "${infiles[@]}"; do
  ...
done

了解更多信息,请阅读bash arrays

如果你不喜欢这个解决方案,你可以用与我在第一段中链接的问题类似some of the answers的方式实现你自己的选项解析。这将允许您获得所需的命令行语义,尽管我认为行为与典型程序的行为方式不一致。