在Bash中使用getopts解析参数时出现错误的Bug问题

9
我正在尝试修改 bd 脚本以使用 getopts。我是 Bash 脚本的新手。
我的脚本如下:
while getopts ":hvis:d:" opt
do
...
done

...

echo $somedirpath
cd "$somedirpath"    

这个短语的意思是“当执行此操作时,这个程序很好地运行”。
$ ./bd -v -i -s search

或者

$ ./bd -is search -d dir

但是,像这样运行它时:
$ . ./bd -s search

"getopts"根本不读取参数。我在"while"循环中根据参数设置的所有变量都没有被设置,因此脚本不再工作。请帮忙!

1
为什么需要加载脚本? - choroba
@choroba 如果没有这个(脚本中的cd在前两种情况下没有影响),目录就不会改变。 - udiboy1209
1
无法在bash3.2或bash4.2中复现。 - chepner
3个回答

10

在调用getopts之前设置OPTIND=1可以正常工作。

问题在于getopts依赖于OPTIND来遍历提供的参数,而在脚本源代码后,getopts将根据传递的参数数量将其设置为大于1的某个值。即使脚本结束(因为它正在被引用),这个值也会保留下来。所以下一次脚本被调用时,getopts将从那个OPTIND开始,而不是从1开始!

这可能会导致其他脚本出现奇怪的行为,我不知道这样做是否安全。但它是可以工作的!

为了更好地解决此问题,我认为@tripleee建议的方法看起来是安全且可靠的。


6

当您使用源代码时,getopts 解析的参数是当前 Shell 的参数,而不是“source”命令行上的参数。

常见的解决方法是让您的脚本仅打印路径,并像 cd "$(bd)" 一样调用它(可能是通过函数或别名间接调用)。


1
但是 echo "$@" 在源代码时显示了正确的参数,对吗? - udiboy1209
此外,它对脚本中的错误语句反应不太好。 - udiboy1209
@tripleee: 来自 help source 的解释:"如果提供了任何参数,它们将在执行 FILENAME 时成为位置参数。" 换句话说,在源脚本内,如果您没有指定任何参数,则继承这些参数;否则,您确实会得到指定的参数。 - rici
是的,这是一个Bash扩展。也是Ksh扩展。可能还有其他的。问题被标记为Bash。 - rici
Github链接后面的脚本有一个#!/bin/sh的shebang行,所以我猜标签实际上是错误的。但感谢您提供的额外信息。 - tripleee
在调用getopts之前,将OPTIND设置为1似乎可以正常工作。但是我采取了完全不使用getopts的不同方法。无论如何,感谢您的帮助。 - udiboy1209

0

在zsh上,设置OPTIND=1可能不太可靠。尝试使用与getopts不同的东西:

while [ "$#" -gt 0 ]
do
   case "$1" in
   -h|--help)
      help
      return 0
      ;;
   -o|--option)
      option
      return 0
      ;;
   -*)
      echo "Invalid option '$1'. Use -h|--help to see the valid options" >&2
      return 1
      ;;
   *)
      echo "Invalid option '$1'. Use -h|--help to see the valid options" >&2
      return 1
   ;;
   esac
   shift
done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接