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

前端 未结 4 1877
遥遥无期
遥遥无期 2021-01-29 22:21

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

script.sh -t application

Firstly, in my script I want to check to see

相关标签:
4条回答
  • 2021-01-29 22:45

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

    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_string: takes any input, and intreprets it as a 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_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_integer: takes an input and intreprets it as an 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

    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

    0 讨论(0)
  • 2021-01-29 23:04

    You should read this getopts tutorial.

    Example with -a switch that requires an argument :

    #!/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) :

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

    0 讨论(0)
  • 2021-01-29 23:07

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

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

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

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

    Finally store $2 in FLAG:

    FLAG=$2
    

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

    function usage {
       cat << EOF
    Usage: script.sh -t <application>
    
    Performs some activity
    EOF
       exit 1
    }
    
    0 讨论(0)
  • 2021-01-29 23:09

    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 [ "$1" ];
    do
        arg=$1
        if [ "${1:0:1}" == "-" ]
        then
          shift
          rev=$(echo "$arg" | rev)
          if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "${rev:0:1}" == ":" ]
          then
            bool=$(echo ${arg:1} | sed s/://g)
            booleans[$bool]=true
            echo \"$bool\" is boolean
          else
            value=$1
            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!

    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.

    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.

    0 讨论(0)
提交回复
热议问题