【问题标题】:Bug in parsing args with getopts in bash在 bash 中使用 getopts 解析 args 的错误
【发布时间】:2014-05-10 13:03:58
【问题描述】:

我试图修改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循环中根据参数设置的所有变量都没有设置,所以脚本不再起作用。请帮忙!

【问题讨论】:

  • 为什么需要 source 脚本?
  • @choroba 没有那个目录不会改变(脚本中的cd在前两种情况下没有效果)
  • 无法在bash 3.2 或bash 4.2 中重现。

标签: bash getopts


【解决方案1】:

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

问题在于getopts 依赖OPTIND 循环提供的参数,并且在获取脚本后,getopts 将根据您传递的参数数量将其设置为大于 1 的值。即使在脚本结束后(因为它是来源的),这个值也会被保留。所以下次它的来源时,getopts 将从那个OPTIND 开始,而不是从 1 开始!

这可能会导致其他脚本出现奇怪的行为,我不知道这有多安全。但它有效!

为了更好的解决方法,我认为@tripleee 的建议看起来既安全又可靠。

【讨论】:

    【解决方案2】:

    当您获取脚本时,getopts 解析的参数是当前 shell 的参数,而不是 source 命令行上的参数。

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

    【讨论】:

    • 但是echo "$@" 向我显示了正确的参数,即使在采购脚本时也是如此?
    • 另外,它不会对脚本中的错误语句做出很好的反应。
    • @tripleee:来自help source:“如果提供了任何参数,则在执行 FILENAME 时它们将成为位置参数。”换句话说,在源脚本中,如果您没有为source 命令指定任何参数,参数将被继承;否则,你确实得到了指定的参数。
    • (是的,它是一个 bash 扩展。也是一个 ksh 扩展。可能还有其他。这个问题被标记为 bash。)
    • Github 链接后面的脚本有一个#!/bin/sh shebang 行,所以我猜实际上标签是错误的。但感谢您提供更多信息。
    猜你喜欢
    • 2011-02-22
    • 2021-04-29
    • 1970-01-01
    • 2012-10-24
    • 2011-10-17
    • 2013-05-15
    • 1970-01-01
    相关资源
    最近更新 更多