在 bash 中检查命令行标志的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2875424/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:17:32  来源:igfitidea点击:

Correct way to check for a command line flag in bash

bashcommand-lineflags

提问by BCS

In the middle of a script, I want to check if a given flag was passed on the command line. The following does what I want but seems ugly:

在脚本中间,我想检查是否在命令行上传递了给定的标志。以下是我想要的,但看起来很丑:

if echo $* | grep -e "--flag" -q
then
  echo ">>>> Running with flag"
else
  echo ">>>> Running without flag"
fi

Is there a better way?

有没有更好的办法?

Note: I explicitly don'twant to list all the flags in a switch/getopt. (In this case any such things would become half or more of the full script. Also the bodies of the if just set a set of vars)

注意:我明确不想在 switch/getopt 中列出所有标志。(在这种情况下,任何此类内容都将成为完整脚本的一半或更多。if 的主体也只是设置了一组变量)

回答by Paused until further notice.

An alternative to what you're doing:

您正在做的事情的替代方案:

if [[ $* == *--flag* ]]

See also BashFAQ/035.

另见BashFAQ/035

Note: This will also match --flags-offsince it's a simple substring check.

注意:这也将匹配,--flags-off因为它是一个简单的子字符串检查。

回答by Kaleb Pederson

I typically see this done with a case statement. Here's an excerpt from the git-repackscript:

我通常看到这是用 case 语句完成的。这是git-repack脚本的摘录:

while test $# != 0
do
    case "" in
    -n) no_update_info=t ;;
    -a) all_into_one=t ;;
    -A) all_into_one=t
        unpack_unreachable=--unpack-unreachable ;;
    -d) remove_redundant=t ;;
    -q) GIT_QUIET=t ;;
    -f) no_reuse=--no-reuse-object ;;
    -l) local=--local ;;
    --max-pack-size|--window|--window-memory|--depth)
        extra="$extra ="; shift ;;
    --) shift; break;;
    *)  usage ;;
    esac
    shift
done

Note that this allows you to check for both short and long flags. Other options are built up using the extravariable in this case.

请注意,这允许您检查短标志和长标志。extra在这种情况下,其他选项是使用变量构建的。

回答by WhirlWind

You can use the getopt keyword in bash.

您可以在 bash 中使用 getopt 关键字。

From http://aplawrence.com/Unix/getopts.html:

来自http://aplawrence.com/Unix/getopts.html

getopt

This is a standalone executable that has been around a long time. Older versions lack the ability to handle quoted arguments (foo a "this won't work" c) and the versions that can, do so clumsily. If you are running a recent Linux version, your "getopt" can do that; SCO OSR5, Mac OS X 10.2.6 and FreeBSD 4.4 has an older version that does not.

The simple use of "getopt" is shown in this mini-script:

获取选择

这是一个已经存在很长时间的独立可执行文件。旧版本缺乏处理引用参数的能力(foo a "this won't work" c),而可以处理的版本笨拙。如果您运行的是最新的 Linux 版本,您的“getopt”可以做到这一点;SCO OSR5、Mac OS X 10.2.6 和 FreeBSD 4.4 的旧版本没有。

这个迷你脚本显示了“getopt”的简单用法:

#!/bin/bash
echo "Before getopt"
for i
do
  echo $i
done
args=`getopt abc:d $*`
set -- $args
echo "After getopt"
for i
do
  echo "-->$i"
done

回答by Eliran Malka

you can take the simple approach, and iterate over the arguments to test each of them for equality with a given parameter (e.g. -t).

您可以采用简单的方法,并迭代参数以测试每个参数与给定参数(例如-t)的相等性。

put it into a function:

把它放到一个函数中:

has_param() {
    local term=""
    shift
    for arg; do
        if [[ $arg == "$term" ]]; then
            return 0
        fi
    done
    return 1
}

… and use it as a predicate in test expressions:

...并将其用作测试表达式中的谓词:

if has_param '-t' "$@"; then
    echo "yay!"
fi

if ! has_param '-t' "" "" "$wat"; then
    echo "nay..."
fi

if you want to reject empty arguments, add an exit point at the top of the loop body:

如果你想拒绝空参数,在循环体的顶部添加一个退出点:

for arg; do
    if [[ -z "$arg" ]]; then
        return 2
    fi
    # ...

this is very readable, and will not give you false positives, like pattern matching or regex matching will.
it will also allow placing flags at arbitrary positions, for example, you can put -hat the end of the command line (not going into whether it's good or bad).

这是非常易读的,不会给你误报,比如模式匹配或正则表达式匹配。
它还允许在任意位置放置标志,例如,您可以放置-h在命令行的末尾(不考虑它的好坏)。



but, the more i thought about it, the more something bothered me.

但是,我想得越多,就越困扰我。

with a function, you can take any implementation (e.g. getopts), and reuse it. encapsulation rulez!
but even with commands, this strength can become a flaw. if you'll be using it again and again, you'll be parsing all the arguments each time.

使用函数,您可以采用任何实现(例如getopts),并重用它。封装规则!
但即使有命令,这种力量也会成为缺陷。如果你一次又一次地使用它,你每次都会解析所有的参数。

my tendency is to favor reuse, but i have to be aware of the implications. the opposed approach would be to parse these arguments once at the script top, as you dreaded, and avoid the repeated parsing.
you can still encapsulate that switch case, which can be as big as you decide (you don't have to list allthe options).

我倾向于重用,但我必须意识到其中的含义。相反的方法是在脚本顶部解析这些参数一次,正如您所担心的那样,并避免重复解析。
您仍然可以封装那个 switch case,它可以像您决定的那样大(您不必列出所有选项)。