【问题标题】:Bash getopt does not accept some of the double dash (--) characterBash getopt 不接受某些双破折号 (--) 字符
【发布时间】:2021-10-07 04:01:09
【问题描述】:

在传递- 字符时使用以下getopt 时出现奇怪的错误。这是代码和输出的示例:

#!/bin/bash

function _echo()
{
  msg="$1"
  # A sample getopt option with only t as short parameter
  # I put -q to silent error and use output based on getopt return status
  options=$(getopt -q -o t -- "$@")
  retval=$?
  if [ ${retval} -ne 0 ]; then
    echo "${msg} <--[this has error]"
  else
    echo "${msg} <--[this is ok]"
  fi
  echo ""
  eval set -- "${options}"
}

# Calling function _echo() without passing any option (sample):

_echo "--" # OK
_echo "Hello" # OK
_echo "Hello--" # OK
_echo "-" # OK
_echo "---------------" # Error
_echo "---" # Error
_echo "--Hello" #Error
_echo "-Hello" #Error

输出:

-- <--[this is ok]

Hello <--[this is ok]

Hello-- <--[this is ok]

- <--[this is ok]

--------------- <--[this has error]

--- <--[this has error]

--Hello <--[this has error]

-Hello <--[this has error]

你可以看到上面传递给_echo函数的一些语句有错误,即使字符串被引用了?如果您想在 _echo 函数中传递长破折号 (-------),如何解决这个问题?

谢谢。

【问题讨论】:

    标签: bash getopt


    【解决方案1】:

    引用无关紧要...调用_echo --Hello 与调用_echo "--Hello" 没有区别。在这两种情况下,_echo 函数都接收一个参数,--Hello。由于您只接受参数-t,任何其他看起来像参数的东西都会导致错误。

    getopt 手册页中描述了处理此问题的正确方法:

    '--' 参数后面的每个参数总是被解释为 非选项参数。如果环境变量 POSIXLY_CORRECT 是 设置,或者如果短选项字符串以“+”开头,则所有剩余 参数被解释为非选项参数 找到第一个非选项参数。

    也就是说,如果你想传入--Hello这样的参数, 你需要像这样打电话给_echo

    _echo -- --Hello
    

    -- 告诉 getopt 任何以下参数都不应被解释为选项,即使它们恰好看起来像一个。

    所以脚本中的示例如下所示:

    _echo "--" # OK
    _echo "Hello" # OK
    _echo "Hello--" # OK
    _echo "-" # OK
    _echo -- "---------------" # Error
    _echo -- "---" # Error
    _echo -- "--Hello" #Error
    _echo -- "-Hello" #Error
    

    这是许多命令行程序的通用约定。


    如您所见,您的_echo 实现存在问题。这是使用getopt 解析选项的典型结构:

    function _echo()
    {
      options=$(getopt -q -o t -- "$@")
      if [ "$?" -ne 0 ]; then
        echo "ERROR: incorrect options in $@"
        return 1
      fi
    
      eval set -- "$options"
      while [ "$#" -gt 0 ]; do
        case $1 in
        (-t)   echo "got -t"
              shift
              ;;
    
        (--)  shift
              break
              ;;
    
        (-*)  echo "unknown option: $1"
              return 1
              ;;
    
        (*)   break
              ;;
        esac
      done
    
      msg=$1
      echo "message is: $msg"
    }
    
    # Calling function _echo() without passing any option (sample):
    
    _echo "--"
    _echo "Hello"
    _echo "Hello--"
    _echo "-"
    _echo -- "---------------"
    _echo -- "---"
    _echo -- "--Hello"
    _echo -- "-Hello"
    _echo -t -- "-Hello"
    

    【讨论】:

    • 谢谢,现在我明白为什么了。我不知道getopt 会关心引用的字符串。现在我正在寻找一种方法让 _echo 函数处理这个错误,而不是修改传递的参数。
    • 我理解这个概念。我没有看输出就接受了答案。因此,当您使用_echo -- "--Hello" 时,它实际上并没有传递字符串 --Hello,而是 msg 只收到了参数 --。所以,这意味着输出在第二个参数中。那么,您认为我应该在 _echo 中进行条件检查还是有办法抑制这种行为。
    • 它确实传递了字符串--Hello。您对 getopt 的调用使用"$@",这是传递给函数的所有参数。处理完所有选项后,您应该只查看$1
    • 是的,我知道我可以使用$* 来获取所有字符串,但这是我们在 getopts 中可以做的唯一方法吗?他们是否有隐藏的选项来克服这个问题。我觉得通过-- 来解决这个问题是一种不好的做法。寻找可以处理此问题的正则表达式条件,如果 msg 包含一些无效字符串,例如仅接受此 (^-.*)$,则我们删除单连字符或双连字符并重新添加字符串。
    • 查看我的更新,其中包括正确实现_echo
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2018-10-08
    • 1970-01-01
    • 2021-07-01
    • 2011-08-28
    • 2015-01-11
    相关资源
    最近更新 更多