【问题标题】:How to search within a range of bash command-line parameters如何在 bash 命令行参数范围内进行搜索
【发布时间】:2020-06-05 20:21:03
【问题描述】:

假设我有一个程序test.sh,它有参数,有些是可选的,有些没有。

例如:

./test.sh --foo /path/to/file --baz --bar1 --bar2 --bar3

其中foobaz 以及路径是必需的,bars 是可选参数。

现在,我希望能够使路径顺序之后的 所有内容 不敏感。

可以使用

if [[ "$3" == "--baz" ]] || [[ "$4" == "--baz" ]] || ... || [[ "${(n-1)}" == "--baz" ]] || [[ "${n}" == "--baz" ]]

但这很慢而且很乱,即使对我来说也是如此。

理想情况下,我会有类似的东西:

if [[ ${n > 2} == "--baz" ]]; then

【问题讨论】:

  • 使用getopt(不是shell内置的getopts,而是GNU程序)来解析你的命令行参数。
  • @chepner 不会搜索整个命令,而不是它的特定部分吗?
  • --baz 之后是否缺少参数?不传达任何信息的强制性论点有什么意义?
  • @chepner 也许我应该说得更好;我的意图是“有必要选择其中一个的几个选项之一”。不过,它也可以与一个额外的论点一起使用——我正在为未来的读者概括我的问题,因为这不是我坚持的部分
  • 不管怎样,使用getopt 之类的东西比重新发明轮子要好。

标签: bash shell parameters


【解决方案1】:

像这样违反标准实用程序语法指南会使您的程序不可预测且难以使用,但您仍然可以这样做,例如具有简单的实用功能:

hasArgAfter() {
  n="$1"
  word="$2"
  shift "$((n+2))"
  for arg
  do
    [ "$arg" = "$word" ] && return 0
  done
  return 1
}

if hasArgAfter 2 "--baz" "$@"
then
  echo "Some argument strictly after #2 is --baz"
fi

【讨论】:

    【解决方案2】:

    根据以下答案:

    你可以想出以下答案:

    [[ " ${@:3} " =~ " --baz " ]] && echo yes || echo no
    

    如果你有类似的东西,这可能会失败

    command --foo /path/to/file --flag1 option1 --flag2 "foo --baz bar" --flag3
    

    其中foo --baz bar--flag2 的一个选项

    另一种更安全的方法是:

    for arg in "${@:3}"; do
       [[ "${arg}" != "--baz" ]] && continue
       # perform action here if --baz is found
       set-of-commands
       # need this line for early return
       break
    done
    

    【讨论】:

      【解决方案3】:

      创建一个处理输入的函数,然后排序就无关紧要了。

      我要做的是使用脚本顶部的 typset 命令为脚本定义全局变量。然后我会使用一个函数来处理用户输入选项,或者只是在没有函数的情况下对其进行编码。这样,当输入不按顺序或丢失时,它会得到正确处理。

      下面的示例使用 case 语句,它使用内置 shift 选项来遍历所有输入。 $1 是 --option $2 是诸如“/path/to/something”之类的值,我在那里检查 $2 是否为空“-z”或||如果不是,请设置它。完成后,项目要么设置要么为空。在您的代码中,您将检查是否设置或为空,以确定您是否要使用该变量(此处未显示。

      # -- create globals --
      typeset fooPath
      typeset baz
      typeset bar1
      
      # -- get required commandline input --
      get_user_input_options() {
        while [[ $# -gt 0 ]] ;do
          key="$1"
          case ${key,,} in
             --foo|--foo-path)
              fooPath="${2}"
              shift
            ;;
            -b|--baz)
              [[ -z "${2}" ]] || baz="${2}"
              shift
            ;;
            --bar1)
              [[ -z "${2}" ]] || bar1="${2}"
              shift
            ;;
            *) echo "ERROR: Unknown option $key given."
              exit 9
            ;;
            esac
            shift
          done
      }
      # -- get inputs first in script logic --
      get_user_input_options "$@"
      echo $fooPath
      echo $baz
      echo $bar1
      

      示例输出:

      [centos@ip-172-31-22-252 ~]$ ./t.sh --foo "/some/thing" --baz askdh
      /some/thing
      askdh
      
      [centos@ip-172-31-22-252 ~]$ ./t.sh --foo "/some/thing" --baz askdh --bar1
      /some/thing
      askdh
      
      [centos@ip-172-31-22-252 ~]$ ./t.sh --foo "/some/thing" --baz askdh --bar1 test
      /some/thing
      askdh
      test
      [centos@ip-172-31-22-252 ~]$ ./t.sh --foo "/some/thing" --baz askdh --bar1 test --notvalid askdha
      ERROR: Unknown option --notvalid given.
      

      【讨论】:

        猜你喜欢
        • 2017-12-09
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-17
        • 2010-09-16
        相关资源
        最近更新 更多