How to get arguments with flags in Bash

后端 未结 11 2095
余生分开走
余生分开走 2020-12-22 15:56

I know that I can easily get positioned parameters like this in bash:

$0 or $1

I want to be able to use flag options like this to s

相关标签:
11条回答
  • 2020-12-22 16:17

    This is the idiom I usually use:

    while test $# -gt 0; do
      case "$1" in
        -h|--help)
          echo "$package - attempt to capture frames"
          echo " "
          echo "$package [options] application [arguments]"
          echo " "
          echo "options:"
          echo "-h, --help                show brief help"
          echo "-a, --action=ACTION       specify an action to use"
          echo "-o, --output-dir=DIR      specify a directory to store output in"
          exit 0
          ;;
        -a)
          shift
          if test $# -gt 0; then
            export PROCESS=$1
          else
            echo "no process specified"
            exit 1
          fi
          shift
          ;;
        --action*)
          export PROCESS=`echo $1 | sed -e 's/^[^=]*=//g'`
          shift
          ;;
        -o)
          shift
          if test $# -gt 0; then
            export OUTPUT=$1
          else
            echo "no output dir specified"
            exit 1
          fi
          shift
          ;;
        --output-dir*)
          export OUTPUT=`echo $1 | sed -e 's/^[^=]*=//g'`
          shift
          ;;
        *)
          break
          ;;
      esac
    done
    

    Key points are:

    • $# is the number of arguments
    • while loop looks at all the arguments supplied, matching on their values inside a case statement
    • shift takes the first one away. You can shift multiple times inside of a case statement to take multiple values.
    0 讨论(0)
  • 2020-12-22 16:18

    If you're familiar with Python argparse, and don't mind calling python to parse bash arguments, there is a piece of code I found really helpful and super easy to use called argparse-bash https://github.com/nhoffman/argparse-bash

    Example take from their example.sh script:

    #!/bin/bash
    
    source $(dirname $0)/argparse.bash || exit 1
    argparse "$@" <<EOF || exit 1
    parser.add_argument('infile')
    parser.add_argument('outfile')
    parser.add_argument('-a', '--the-answer', default=42, type=int,
                        help='Pick a number [default %(default)s]')
    parser.add_argument('-d', '--do-the-thing', action='store_true',
                        default=False, help='store a boolean [default %(default)s]')
    parser.add_argument('-m', '--multiple', nargs='+',
                        help='multiple values allowed')
    EOF
    
    echo required infile: "$INFILE"
    echo required outfile: "$OUTFILE"
    echo the answer: "$THE_ANSWER"
    echo -n do the thing?
    if [[ $DO_THE_THING ]]; then
        echo " yes, do it"
    else
        echo " no, do not do it"
    fi
    echo -n "arg with multiple values: "
    for a in "${MULTIPLE[@]}"; do
        echo -n "[$a] "
    done
    echo
    
    0 讨论(0)
  • 2020-12-22 16:21
    #!/bin/bash
    
    if getopts "n:" arg; then
      echo "Welcome $OPTARG"
    fi
    

    Save it as sample.sh and try running

    sh sample.sh -n John
    

    in your terminal.

    0 讨论(0)
  • 2020-12-22 16:26

    This example uses Bash's built-in getopts command and is from the Google Shell Style Guide:

    a_flag=''
    b_flag=''
    files=''
    verbose='false'
    
    print_usage() {
      printf "Usage: ..."
    }
    
    while getopts 'abf:v' flag; do
      case "${flag}" in
        a) a_flag='true' ;;
        b) b_flag='true' ;;
        f) files="${OPTARG}" ;;
        v) verbose='true' ;;
        *) print_usage
           exit 1 ;;
      esac
    done
    

    Note: If a character is followed by a colon (e.g. f:), that option is expected to have an argument.

    Example usage: ./script -v -a -b -f filename

    Using getopts has several advantages over the accepted answer:

    • the while condition is a lot more readable and shows what the accepted options are
    • cleaner code; no counting the number of parameters and shifting
    • you can join options (e.g. -a -b -c-abc)

    However, a big disadvantage is that it doesn't support long options, only single-character options.

    0 讨论(0)
  • 2020-12-22 16:26

    I propose a simple TLDR:; example for the un-initiated.

    Create a bash script called helloworld.sh

    #!/bin/bash
    
    while getopts "n:" arg; do
      case $arg in
        n) Name=$OPTARG;;
      esac
    done
    
    echo "Hello $Name!"
    

    You can then pass an optional parameter -n when executing the script.

    Execute the script as such:

    $ bash helloworld.sh -n 'World'
    

    Output

    $ Hello World!
    

    Notes

    If you'd like to use multiple parameters:

    1. extend while getops "n:" arg: do with more paramaters such as while getops "n:o:p:" arg: do
    2. extend the case switch with extra variable assignments. Such as o) Option=$OPTARG and p) Parameter=$OPTARG
    0 讨论(0)
提交回复
热议问题