Passing parameters to a Bash function

前端 未结 7 1174
北荒
北荒 2020-11-22 10:15

I am trying to search how to pass parameters in a Bash function, but what comes up is always how to pass parameter from the command line.

I would like to pass param

7条回答
  •  无人及你
    2020-11-22 10:48

    If you prefer named parameters, it's possible (with a few tricks) to actually pass named parameters to functions (also makes it possible to pass arrays and references).

    The method I developed allows you to define named parameters passed to a function like this:

    function example { args : string firstName , string lastName , integer age } {
      echo "My name is ${firstName} ${lastName} and I am ${age} years old."
    }
    

    You can also annotate arguments as @required or @readonly, create ...rest arguments, create arrays from sequential arguments (using e.g. string[4]) and optionally list the arguments in multiple lines:

    function example {
      args
        : @required string firstName
        : string lastName
        : integer age
        : string[] ...favoriteHobbies
    
      echo "My name is ${firstName} ${lastName} and I am ${age} years old."
      echo "My favorite hobbies include: ${favoriteHobbies[*]}"
    }
    

    In other words, not only you can call your parameters by their names (which makes up for a more readable core), you can actually pass arrays (and references to variables - this feature works only in bash 4.3 though)! Plus, the mapped variables are all in the local scope, just as $1 (and others).

    The code that makes this work is pretty light and works both in bash 3 and bash 4 (these are the only versions I've tested it with). If you're interested in more tricks like this that make developing with bash much nicer and easier, you can take a look at my Bash Infinity Framework, the code below is available as one of its functionalities.

    shopt -s expand_aliases
    
    function assignTrap {
      local evalString
      local -i paramIndex=${__paramIndex-0}
      local initialCommand="${1-}"
    
      if [[ "$initialCommand" != ":" ]]
      then
        echo "trap - DEBUG; eval \"${__previousTrap}\"; unset __previousTrap; unset __paramIndex;"
        return
      fi
    
      while [[ "${1-}" == "," || "${1-}" == "${initialCommand}" ]] || [[ "${#@}" -gt 0 && "$paramIndex" -eq 0 ]]
      do
        shift # first colon ":" or next parameter's comma ","
        paramIndex+=1
        local -a decorators=()
        while [[ "${1-}" == "@"* ]]
        do
          decorators+=( "$1" )
          shift
        done
    
        local declaration=
        local wrapLeft='"'
        local wrapRight='"'
        local nextType="$1"
        local length=1
    
        case ${nextType} in
          string | boolean) declaration="local " ;;
          integer) declaration="local -i" ;;
          reference) declaration="local -n" ;;
          arrayDeclaration) declaration="local -a"; wrapLeft= ; wrapRight= ;;
          assocDeclaration) declaration="local -A"; wrapLeft= ; wrapRight= ;;
          "string["*"]") declaration="local -a"; length="${nextType//[a-z\[\]]}" ;;
          "integer["*"]") declaration="local -ai"; length="${nextType//[a-z\[\]]}" ;;
        esac
    
        if [[ "${declaration}" != "" ]]
        then
          shift
          local nextName="$1"
    
          for decorator in "${decorators[@]}"
          do
            case ${decorator} in
              @readonly) declaration+="r" ;;
              @required) evalString+="[[ ! -z \$${paramIndex} ]] || echo \"Parameter '$nextName' ($nextType) is marked as required by '${FUNCNAME[1]}' function.\"; " >&2 ;;
              @global) declaration+="g" ;;
            esac
          done
    
          local paramRange="$paramIndex"
    
          if [[ -z "$length" ]]
          then
            # ...rest
            paramRange="{@:$paramIndex}"
            # trim leading ...
            nextName="${nextName//\./}"
            if [[ "${#@}" -gt 1 ]]
            then
              echo "Unexpected arguments after a rest array ($nextName) in '${FUNCNAME[1]}' function." >&2
            fi
          elif [[ "$length" -gt 1 ]]
          then
            paramRange="{@:$paramIndex:$length}"
            paramIndex+=$((length - 1))
          fi
    
          evalString+="${declaration} ${nextName}=${wrapLeft}\$${paramRange}${wrapRight}; "
    
          # continue to the next param:
          shift
        fi
      done
      echo "${evalString} local -i __paramIndex=${paramIndex};"
    }
    
    alias args='local __previousTrap=$(trap -p DEBUG); trap "eval \"\$(assignTrap \$BASH_COMMAND)\";" DEBUG;'
    

提交回复
热议问题