Linux Bash Shell 脚本 - 检查标志并获取其值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14447406/
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-08-06 18:45:19  来源:igfitidea点击:

Bash Shell Script - Check for a flag and grab its value

linuxbashshelldebian

提问by Jimmy

I am trying to make a shell script which is designed to be run like this:

我正在尝试制作一个 shell 脚本,该脚本旨在像这样运行:

script.sh -t application

Firstly, in my script I want to check to see if the script has been run with the -t flag. For example if it has been run without the flag like this I want it to error:

首先,在我的脚本中,我想检查脚本是否已使用 -t 标志运行。例如,如果它在没有像这样的标志的情况下运行,我希望它出错:

script.sh

Secondly, assuming there is a -t flag, I want to grab the value and store it in a variable that I can use in my script for example like this:

其次,假设有一个 -t 标志,我想获取该值并将其存储在我可以在我的脚本中使用的变量中,例如:

FLAG="application"

So far the only progress I've been able to make on any of this is that $@ grabs all the command line arguments but I don't know how this relates to flags, or if this is even possible.

到目前为止,我在这方面取得的唯一进展是 $@ 获取了所有命令行参数,但我不知道这与标志有什么关系,或者这是否可能。

采纳答案by Gilles Quenot

You should read this getoptstutorial.

你应该阅读这个getopts教程。

Example with -aswitch that requires an argument :

-a需要参数的开关示例:

#!/bin/bash

while getopts ":a:" opt; do
  case $opt in
    a)
      echo "-a was triggered, Parameter: $OPTARG" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

Like greybot said(getopt!= getopts) :

就像灰色机器人说的(getopt!= getopts):

The external command getopt(1) is never safe to use, unless you knowit is GNU getopt, you call it in a GNU-specific way, andyou ensure that GETOPT_COMPATIBLE is not in the environment. Use getopts (shell builtin) instead, or simply loop over the positional parameters.

外部命令 getopt(1) 永远不能安全使用,除非您知道它是 GNU getopt,您以特定于 GNU 的方式调用它,并且您确保环境中没有 GETOPT_COMPATIBLE。改用 getopts(shell 内置),或者简单地循环遍历位置参数。

回答by Veger

Use $#to grab the number of arguments, if it is unequal to 2 there are not enough arguments provided:

$#抢的参数的数目,如果它不等于2有没有提供了足够的论据:

if [ $# -ne 2 ]; then
   usage;
fi

Next, check if $1equals -t, otherwise an unknown flag was used:

接下来,检查是否$1等于-t,否则使用了未知标志:

if [ "" != "-t" ]; then
  usage;
fi

Finally store $2in FLAG:

最后存储$2FLAG

FLAG=

Note: usage()is some function showing the syntax. For example:

注意:usage()是一些显示语法的函数。例如:

function usage {
   cat << EOF
Usage: script.sh -t <application>

Performs some activity
EOF
   exit 1
}

回答by Anandkumar

Try shFlags -- Advanced command-line flag library for Unix shell scripts.

试试 shFlags——Unix shell 脚本的高级命令行标志库。

http://code.google.com/p/shflags/

http://code.google.com/p/shflags/

It is very good and very flexible.

它非常好,非常灵活。

FLAG TYPES: This is a list of the DEFINE_*'s that you can do. All flags take a name, default value, help-string, and optional 'short' name (one-letter name). Some flags have other arguments, which are described with the flag.

标志类型:这是您可以执行的 DEFINE_* 的列表。所有标志都采用名称、默认值、帮助字符串和可选的“短”名称(一个字母的名称)。一些标志有其他参数,这些参数用标志描述。

DEFINE_string: takes any input, and intreprets it as a string.

DEFINE_string:接受任何输入,并将其解释为字符串。

DEFINE_boolean: typically does not take any argument: say --myflag to set FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false. Alternately, you can say --myflag=true or --myflag=t or --myflag=0 or --myflag=false or --myflag=f or --myflag=1 Passing an option has the same affect as passing the option once.

DEFINE_boolean:通常不带任何参数:说--myflag 将FLAGS_myflag 设置为true,或--nomyflag 将FLAGS_myflag 设置为false。或者,您可以说 --myflag=true 或 --myflag=t 或 --myflag=0 或 --myflag=false 或 --myflag=f 或 --myflag=1 传递选项与传递选项具有相同的效果选项一次。

DEFINE_float: takes an input and intreprets it as a floating point number. As shell does not support floats per-se, the input is merely validated as being a valid floating point value.

DEFINE_float:接受输入并将其解释为浮点数。由于 shell 本身不支持浮点数,因此输入仅被验证为有效的浮点值。

DEFINE_integer: takes an input and intreprets it as an integer.

DEFINE_integer:接受输入并将其解释为整数。

SPECIAL FLAGS: There are a few flags that have special meaning: --help (or -?) prints a list of all the flags in a human-readable fashion --flagfile=foo read flags from foo. (not implemented yet) -- as in getopt(), terminates flag-processing

特殊标志:有一些标志具有特殊含义:--help(或-?)以人类可读的方式打印所有标志的列表--flagfile=foo 从 foo 中读取标志。(尚未实现)——如在 getopt() 中,终止标志处理

EXAMPLE USAGE:

用法示例:

-- begin hello.sh --
 ! /bin/sh
. ./shflags
DEFINE_string name 'world' "somebody's name" n
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
echo "Hello, ${FLAGS_name}."
-- end hello.sh --

$ ./hello.sh -n Kate
Hello, Kate.

Note: I took this text from shflags documentation

注意:我从 shflags 文档中获取了此文本

回答by jozsef morrissey

Here is a generalized simple command argument interface you can paste to the top of all your scripts.

这是一个通用的简单命令参数界面,您可以将其粘贴到所有脚本的顶部。

#!/bin/bash

declare -A flags
declare -A booleans
args=()

while [ "" ];
do
    arg=
    if [ "${1:0:1}" == "-" ]
    then
      shift
      rev=$(echo "$arg" | rev)
      if [ -z "" ] || [ "${1:0:1}" == "-" ] || [ "${rev:0:1}" == ":" ]
      then
        bool=$(echo ${arg:1} | sed s/://g)
        booleans[$bool]=true
        echo \"$bool\" is boolean
      else
        value=
        flags[${arg:1}]=$value
        shift
        echo \"$arg\" is flag with value \"$value\"
      fi
    else
      args+=("$arg")
      shift
      echo \"$arg\" is an arg
    fi
done


echo -e "\n"
echo booleans: ${booleans[@]}
echo flags: ${flags[@]}
echo args: ${args[@]}

echo -e "\nBoolean types:\n\tPrecedes Flag(pf): ${booleans[pf]}\n\tFinal Arg(f): ${booleans[f]}\n\tColon Terminated(Ct): ${booleans[Ct]}\n\tNot Mentioned(nm): ${boolean[nm]}"
echo -e "\nFlag: myFlag => ${flags["myFlag"]}"
echo -e "\nArgs: one: ${args[0]}, two: ${args[1]}, three: ${args[2]}"

By running the command:

通过运行命令:

bashScript.sh firstArg -pf -myFlag "my flag value" secondArg -Ct: thirdArg -f

The output will be this:

输出将是这样的:

"firstArg" is an arg
"pf" is boolean
"-myFlag" is flag with value "my flag value"
"secondArg" is an arg
"Ct" is boolean
"thirdArg" is an arg
"f" is boolean


booleans: true true true
flags: my flag value
args: firstArg secondArg thirdArg

Boolean types:
    Precedes Flag(pf): true
    Final Arg(f): true
    Colon Terminated(Ct): true
    Not Mentioned(nm): 

Flag: myFlag => my flag value

Args: one => firstArg, two => secondArg, three => thirdArg

Basically, the arguments are divided up into flags booleans and generic arguments. By doing it this way a user can put the flags and booleans anywhere as long as he/she keeps the generic arguments (if there are any) in the specified order.

基本上,参数分为标志布尔值和通用参数。通过这样做,用户可以将标志和布尔值放在任何地方,只要他/她按指定的顺序保留通用参数(如果有的话)。

Allowing me and now you to never deal with bash argument parsing again!

让我和现在你再也不用处理 bash 参数解析了!

You can view an updated script here

您可以在此处查看更新的脚本

This has been enormously useful over the last year. It can now simulate scope by prefixing the variables with a scope parameter.

这在过去一年中非常有用。它现在可以通过在变量前加上 scope 参数来模拟作用域。

Just call the script like

只需调用脚本

replace() (
  source $FUTIL_REL_DIR/commandParser.sh -scope ${FUNCNAME[0]} "$@"
  echo ${replaceFlags[f]}
  echo ${replaceBooleans[b]}
)

Doesn't look like I implemented argument scope, not sure why I guess I haven't needed it yet.

看起来我没有实现参数范围,不知道为什么我猜我还不需要它。