bash getopts无法识别第二个参数

bash getopts无法识别第二个参数,bash,getopts,Bash,Getopts,这是我的整个脚本的最简单形式 #!/bin/bash src="" targ=${PWD} while getopts "s:t:" opt; do case $opt in s) src=$OPTARG ;; t) targ=$OPTARG ;; esac shift $((OPTIND-1)) done echo "Source: $src" echo "Target: $targ" 我以getopts\u t

这是我的整个脚本的最简单形式

#!/bin/bash
src=""
targ=${PWD}

while getopts "s:t:" opt; do
  case $opt in
    s)
      src=$OPTARG
      ;;
    t)
      targ=$OPTARG
      ;;
  esac
  shift $((OPTIND-1))
done

echo "Source: $src"
echo "Target: $targ"
我以
getopts\u test-sa-tb

但是,它总是在
目标前面打印
pwd
,而从不打印
b


这里我遗漏了什么?

为什么从不打印
b
的原因是循环中的
移位
在第一次迭代后,即打印
a
后,将处理过的选项移开。使用
shift$((OPTIND-1))
旨在访问可能的给定可变参数。当然,一旦您删除
shift
targ
将被重新分配到
b
,并且
${PWD}
不再包含在其中,因为您在任何地方都没有串接字符串(
targ
-t
选项)。

这是@glenn jackman在其评论中建议的替代方案 是这样的:

#!/bin/bash
src=""
targ=${PWD}

while getopts "s:t:" opt; do
  case $opt in
    s)
      src=$OPTARG
      echo "Source: $src"
      ;;
    t)
      targ=$OPTARG
      echo "Target: $targ"
      ;;
  esac

done

shift $((OPTIND-1)) # Turning to non-option arguments say a file name and so on.

在这里,您可以使用自然的参数流,而不必使用
shift
ing。

这可能有助于尝试将
shift
从while循环中移除:将其移动到
done
之后当您在循环中进行移位时,您从参数列表中移除
-s
a
参数,但是
getopts
仍然认为它处理了参数1和2(现在包含
-t
b
),所以它超越了它们,说“没有别的事可做”。明白了。感谢您的详细解释循环后需要移位,这样您就可以删除选项参数(和
--
),而只保留
“$@”
非选项参数。@JonathanLeffler:感谢您提醒非选项参数。编辑答案。:)