如何在 bash 中结合 getopts 和位置参数? [复制]

Posted

技术标签:

【中文标题】如何在 bash 中结合 getopts 和位置参数? [复制]【英文标题】:How to combine getopts and positional parameters in bash? [duplicate] 【发布时间】:2018-03-03 06:23:10 【问题描述】:

我想同时使用getopts 和位置参数,但是如果我将位置参数传递给程序,getopts 就会丢失。

directory=$1

while getopts l: flag; do
  case "$flag" in
    l) level=$OPTARG;;
  esac
done

if [ -n "$level" ]; then
  echo "Level exist!"
else
  echo "Level doesn't exist!"
fi

所以当我这样运行程序时:

sh myprogram.sh ~/documents -l 2

我希望:

Level exist!

而是返回:

Level doesn't exist!

问题是,如果我在没有位置参数(~/documents)的情况下运行程序,如下所示:

sh myprogram.sh -l 2

我得到正确的输出:

Level exist!

这是为什么呢?如何在 bash 中同时使用位置参数和 getopts

谢谢!

【问题讨论】:

如果您确定第一个位置参数将是您的目录,您可以在分配directory=$1 之后使用shift。但是,正如所指出的,遵循既定做法可能会更好。 【参考方案1】:

大部分工具都写成这样的形式:tool [options] arg ...

所以你会这样做:

# first, parse the options:
while getopts l: flag; do
  case "$flag" in
    l) level=$OPTARG;;
    \?) exit 42;;
  esac
done

# and shift them away
shift $((OPTIND - 1))

# validation
if [ -n "$level" ]; then
  echo "Level exist!"
else
  echo "Level doesn't exist!"
fi

# THEN, access the positional params
echo "there are $# positional params remaining"
for ((i=1; i<=$#; i++)); do
  printf "%d\t%s\n" $i "$!i"
done

如果用户提供未知选项或未能提供所需参数,请使用 \? 中止脚本

然后像这样调用它:

$ bash test.sh
Level doesn't exist!
there are 0 positional params remaining

$ bash test.sh -l 2
Level exist!
there are 0 positional params remaining

$ bash test.sh -l 2 foo bar
Level exist!
there are 2 positional params remaining
1   foo
2   bar

$ bash test.sh -x
test.sh: illegal option -- x

$ bash test.sh -l
test.sh: option requires an argument -- l

但是您不能将选项放在参数之后:当找到第一个非选项参数时 getopts 停止

$ bash test.sh foo bar -l 2
Level doesn't exist!
there are 4 positional params remaining
1   foo
2   bar
3   -l
4   2

【讨论】:

不错!它起作用了,所以没有任何解决方法可以将 opts 放在参数之后? 不适用于getopts。有一个外部程序调用getopt 可以做到这一点。使用起来有点困难。这是一个示例:bazaar.launchpad.net/~ubuntu-branches/ubuntu/vivid/util-linux/…

以上是关于如何在 bash 中结合 getopts 和位置参数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 bash 中使用 getopts 的示例

在 Bash 中使用 getopts 检索单个选项的多个参数

当 Bash 和 GETOPTS 中没有设置 $OPTARG 时,有没有办法在 Flag 中继续?

sh 如何使用bash / getopt解析选项的示例

在 bash 中使用 getopts 的布尔 cli 标志?

在 Bash 函数中使用 getopts