[bash] Bash 함수에 매개 변수 전달

Bash 함수에서 매개 변수를 전달하는 방법을 검색하려고하지만 항상 명령 줄에서 매개 변수를 전달하는 방법이 있습니다.

스크립트 내에서 매개 변수를 전달하고 싶습니다. 나는 시도했다 :

myBackupFunction("..", "...", "xx")

function myBackupFunction($directory, $options, $rootPassword) {
     ...
}

그러나 구문이 올바르지 않습니다. 매개 변수를 함수에 전달하는 방법은 무엇입니까?



답변

함수를 선언하는 일반적인 두 가지 방법이 있습니다. 나는 두 번째 접근법을 선호합니다.

function function_name {
   command...
} 

또는

function_name () {
   command...
} 

인수가있는 함수를 호출하려면

function_name "$arg1" "$arg2"

이 함수는 이름이 아닌 위치에 따라 전달 된 인수, 즉 $ 1, $ 2 등을 나타냅니다. $ 0 은 스크립트 자체의 이름입니다.

예:

function_name () {
   echo "Parameter #1 is $1"
}

또한 함수 가 선언 된 후에 함수를 호출해야합니다 .

#!/usr/bin/env sh

foo 1  # this will fail because foo has not been declared yet.

foo() {
    echo "Parameter #1 is $1"
}

foo 2 # this will work.

산출:

./myScript.sh: line 2: foo: command not found
Parameter #1 is 2

참조 : Advanced Bash-Scripting Guide .


답변

고급 프로그래밍 언어 (C / C ++ / Java / PHP / Python / Perl …)에 대한 지식은 일반인에게 bash 함수가 다른 언어에서와 같이 작동해야 함을 제안합니다. 대신 , bash 함수는 쉘 명령처럼 작동하며 옵션을 쉘 명령 (예 :)에 전달할 수있는 것과 같은 방식으로 인수가 전달 될 것으로 예상합니다 ls -l. 실제로 bash의 함수 인수위치 매개 변수 ( $1, $2..$9, ${10}, ${11}등) 로 처리됩니다 . getopts작동 방식을 고려해도 놀라운 일이 아닙니다 . 괄호를 사용하여 bash에서 함수를 호출하지 마십시오.


( 참고 : 현재 Open Solaris에서 작업 중입니다.)

# bash style declaration for all you PHP/JavaScript junkies. :-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
function backupWebRoot ()
{
    tar -cvf - $1 | zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


# sh style declaration for the purist in you. ;-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
backupWebRoot ()
{
    tar -cvf - $1 | zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


# In the actual shell script
# $0               $1            $2

backupWebRoot ~/public/www/ webSite.tar.zip

변수 이름을 사용하려고합니다. 그냥하세요

declare filename=$1 # declare gives you more options and limits variable scope

배열을 함수에 전달하고 싶습니까?

callingSomeFunction "${someArray[@]}" # Expands to all array elements.

함수 내에서 이와 같은 인수를 처리하십시오.

function callingSomeFunction ()
{
    for value in "$@" # You want to use "$@" here, not "$*" !!!!!
    do
        :
    done
}

값과 배열을 전달해야하지만 여전히 함수 내에서 “$ @”를 사용합니까?

function linearSearch ()
{
    declare myVar="$1"

    shift 1 # removes $1 from the parameter list

    for value in "$@" # Represents the remaining parameters.
    do
        if [[ $value == $myVar ]]
        then
            echo -e "Found it!\t... after a while."
            return 0
        fi
    done

    return 1
}

linearSearch $someStringValue "${someArray[@]}"


답변

명명 된 매개 변수를 선호하는 경우 실제로 몇 가지 트릭을 사용하여 명명 된 매개 변수를 함수에 전달할 수도 있습니다 (배열과 참조를 전달할 수도 있습니다).

내가 개발 한 방법을 사용하면 다음과 같은 함수에 전달 된 명명 된 매개 변수를 정의 할 수 있습니다.

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

또한 @required 또는 @readonly로 인수에 주석을 달고 … rest 인수를 작성하고 순차적 인수에서 배열을 작성하고 (예 :를 사용하여 string[4]) 선택적으로 인수를 여러 줄에 나열 할 수 있습니다.

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[*]}"
}

다시 말해, 이름으로 매개 변수를 호출 할 수있을뿐만 아니라 (더 읽기 쉬운 코어를 구성 함) 실제로 배열을 전달할 수 있습니다 (변수에 대한 참조-이 기능은 bash 4.3에서만 작동합니다). 또한 매핑 된 변수는 모두 $ 1 (및 기타)과 같이 로컬 범위에 있습니다.

이 작업을 수행하는 코드는 매우 가볍고 bash 3 및 bash 4에서 모두 작동합니다 (이것은 내가 테스트 한 유일한 버전입니다). bash로 개발하는 것을 훨씬 더 좋고 쉽게 만드는 더 많은 트릭에 관심이 있다면 내 Bash Infinity Framework를 살펴보십시오. 아래 코드는 기능 중 하나입니다.

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;'


답변

괄호와 쉼표를 놓치십시오.

 myBackupFunction ".." "..." "xx"

함수는 다음과 같아야합니다.

function myBackupFunction() {
   # here $1 is the first parameter, $2 the second etc.
}


답변

이 예제가 도움이되기를 바랍니다. 사용자로부터 두 개의 숫자를 가져 와서 add(코드의 마지막 줄에서) 호출 된 함수에 공급하고 add합계하여 인쇄합니다.

#!/bin/bash

read -p "Enter the first  value: " x
read -p "Enter the second value: " y

add(){
    arg1=$1 #arg1 gets to be the first  assigned argument (note there are no spaces)
    arg2=$2 #arg2 gets to be the second assigned argument (note there are no spaces)

    echo $(($arg1 + $arg2))
}

add x y #feeding the arguments


답변

스크립트를 실행하는 동안 또는 함수를 호출하는 동안 내부 스크립트를 모두 지우는 간단한 예입니다.

#!/bin/bash
echo "parameterized function example"
function print_param_value(){
    value1="${1}" # $1 represent first argument
    value2="${2}" # $2 represent second argument
    echo "param 1 is  ${value1}" #as string
    echo "param 2 is ${value2}"
    sum=$(($value1+$value2)) #process them as number
    echo "The sum of two value is ${sum}"
}
print_param_value "6" "4" #space sparted value
#you can also pass paramter durign executing script
print_param_value "$1" "$2" #parameter $1 and $2 during executing

#suppose our script name is param_example
# call like this 
# ./param_example 5 5
# now the param will be $1=5 and $2=5


답변

명명 된 매개 변수를 bash에 전달하는 다른 방법을 언급하면서 참조로 전달한다고 생각했습니다. 이것은 bash 4.0부터 지원됩니다

#!/bin/bash
function myBackupFunction(){ # directory options destination filename
local directory="$1" options="$2" destination="$3" filename="$4";
  echo "tar cz ${!options} ${!directory} | ssh root@backupserver \"cat > /mnt/${!destination}/${!filename}.tgz\"";
}

declare -A backup=([directory]=".." [options]="..." [destination]="backups" [filename]="backup" );

myBackupFunction backup[directory] backup[options] backup[destination] backup[filename];

bash 4.3의 다른 구문은 nameref를 사용하는 것입니다

nameref가 완벽하게 역 참조된다는 점에서 훨씬 편리하지만, 일부 이전 지원되는 배포판은 여전히 이전 버전을 제공 하므로 아직 권장하지 않습니다.