当参数以 - 开头时如何转移参数

当参数以 - 开头时如何转移参数

假设我有一个 bash 函数,它应该删除所有以“-”开头的参数,直到它到达不以“-”开头的参数。

gmx(){

  local options=( );

  while [ "${1:0:1}" == "-"  ]; do
    options+=("${1}")
    shift 1;
  done

  echo "first legit arg: $1"
  "$@" # omg will be executed here, like `omg --rolo`
}

gmx -a -f -c omg --rolo

这似乎有效,但我想知道这是否是一个很好的通用解决方案,可以始终让“omg”成为第一个“合法”参数。是否存在可能失败的边缘情况?

换句话说,-a、-f、-c 都是 gmx 的参数。而omg接下来的一切都将在子进程中运行。

答案1

官方和最好的方法是不要使用getopts内置函数来解析命令行选项。

请参阅手册页以获取更多信息。

注释可能很重要:bash不支持长选项。

如果您喜欢脚本来处理长选项,您有两个支持它们的 shell:ksh93bosh。两个 shell 都支持长选项,就像getopt(3)Solaris 上 libc 中的函数支持它们一样。请参阅 bosh 手册页(当前从第 43 页开始:

http://schilytools.sourceforge.net/man/man1/bosh.1.html

getopts "f:(file)(input-file)o:(output-file)" OPT

-f支持例如带有参数的选项,并且该选项具有长选项别名--file和该选项的第二个别名--input-file

ksh93 也支持这一点,尽管 ksh93 手册页中没有对此进行记录。

答案2

while getopts ':' opt; do
    :    # This is where ordinarily a case statement would be,
         # case $opt in ... esac
         # But we use : as a no-op
done

shift "$(( OPTIND - 1 ))"
printf 'arg: %s\n' "$@"

这用于getopts解析命令行选项。while一旦找到第一个非选项,循环就会终止,并且会将shift已处理的选项移走,$@只留下非选项操作数$@

剧本

#!/bin/sh

gmx () {
    while getopts ':' opt; do
        :
    done

    shift "$(( OPTIND - 1 ))"
    printf 'arg: %s\n' "$@"
}

gmx -a --foo -c omg lol

会输出

arg: omg
arg: lol

由于您对真正的选项不感兴趣,因此您显然可以执行一个简单的循环,例如

for opt do
    case $opt in
        -*) shift ;;
        *)  break
     esac
done

printf 'arg: %s\n' "$@"

这会循环遍历所有参数,将每个以破折号开头的参数移开,并以第一个不以破折号开头的参数结束。

答案3

如果你能控制方式,一个更简单的解决方案GMX被调用,只是使用 来将包装器的参数与包装的命令分开--,这样

gmx garg garg garg -- warg warg warg

在哪里

  • 加尔格表示使用的参数GMX
  • 座狼表示发送到的参数包装纸

如果您想要方便地省略--,您可以将其设为可选,并在尝试“智能”检查之前搜索它。

相关内容