How to iterate over arguments in a Bash script

后端 未结 8 2583
长发绾君心
长发绾君心 2020-11-22 02:27

I have a complex command that I\'d like to make a shell/bash script of. I can write it in terms of $1 easily:

foo $1 args -o $1.ext


        
相关标签:
8条回答
  • 2020-11-22 03:08

    Use "$@" to represent all the arguments:

    for var in "$@"
    do
        echo "$var"
    done
    

    This will iterate over each argument and print it out on a separate line. $@ behaves like $* except that when quoted the arguments are broken up properly if there are spaces in them:

    sh test.sh 1 2 '3 4'
    1
    2
    3 4
    
    0 讨论(0)
  • 2020-11-22 03:10

    Amplifying on baz's answer, if you need to enumerate the argument list with an index (such as to search for a specific word), you can do this without copying the list or mutating it.

    Say you want to split an argument list at a double-dash ("--") and pass the arguments before the dashes to one command, and the arguments after the dashes to another:

     toolwrapper() {
       for i in $(seq 1 $#); do
         [[ "${!i}" == "--" ]] && break
       done || return $? # returns error status if we don't "break"
    
       echo "dashes at $i"
       echo "Before dashes: ${@:1:i-1}"
       echo "After dashes: ${@:i+1:$#}"
     }
    

    Results should look like this:

     $ toolwrapper args for first tool -- and these are for the second
     dashes at 5
     Before dashes: args for first tool
     After dashes: and these are for the second
    
    0 讨论(0)
  • 2020-11-22 03:10

    getopt Use command in your scripts to format any command line options or parameters.

    #!/bin/bash
    # Extract command line options & values with getopt
    #
    set -- $(getopt -q ab:cd "$@")
    #
    echo
    while [ -n "$1" ]
    do
    case "$1" in
    -a) echo "Found the -a option" ;;
    -b) param="$2"
    echo "Found the -b option, with parameter value $param"
    shift ;;
    -c) echo "Found the -c option" ;;
    --) shift
    break ;;
    *) echo "$1 is not an option";;
    esac
    shift
    
    0 讨论(0)
  • 2020-11-22 03:12

    You can also access them as an array elements, for example if you don't want to iterate through all of them

    argc=$#
    argv=("$@")
    
    for (( j=0; j<argc; j++ )); do
        echo "${argv[j]}"
    done
    
    0 讨论(0)
  • 2020-11-22 03:18

    For simple cases you can also use shift. It treats the argument list like a queue. Each shift throws the first argument out and the index of each of the remaining arguments is decremented.

    #this prints all arguments
    while test $# -gt 0
    do
        echo "$1"
        shift
    done
    
    0 讨论(0)
  • 2020-11-22 03:23

    Note that Robert's answer is correct, and it works in sh as well. You can (portably) simplify it even further:

    for i in "$@"
    

    is equivalent to:

    for i
    

    I.e., you don't need anything!

    Testing ($ is command prompt):

    $ set a b "spaces here" d
    $ for i; do echo "$i"; done
    a
    b
    spaces here
    d
    $ for i in "$@"; do echo "$i"; done
    a
    b
    spaces here
    d
    

    I first read about this in Unix Programming Environment by Kernighan and Pike.

    In bash, help for documents this:

    for NAME [in WORDS ... ;] do COMMANDS; done

    If 'in WORDS ...;' is not present, then 'in "$@"' is assumed.

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