将参数传递给 Bash 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6212219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:35:48  来源:igfitidea点击:

Passing parameters to a Bash function

bashparametersarguments

提问by stivlo

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.

我试图搜索如何在 Bash 函数中传递参数,但出现的总是如何从命令行传递参数。

I would like to pass parameters within my script. I tried:

我想在我的脚本中传递参数。我试过:

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

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

But the syntax is not correct, how to pass a parameter to my function?

但是语法不对,怎么给我的函数传递参数?

回答by dogbane

There are two typical ways of declaring a function. I prefer the second approach.

有两种典型的函数声明方式。我更喜欢第二种方法。

function function_name {
   command...
} 

or

或者

function_name () {
   command...
} 

To call a function with arguments:

调用带参数的函数:

function_name "$arg1" "$arg2"

The function refers to passed arguments by their position (not by name), that is $1, $2, and so forth. $0is the name of the script itself.

该函数通过它们的位置(而不是名称)来引用传递的参数,即 $1、$2 等等。$0是脚本本身的名称。

Example:

例子:

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

Also, you need to call your function afterit is declared.

此外,您需要声明调用您的函数。

#!/usr/bin/env sh

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

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

foo 2 # this will work.

Output:

输出:

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

Reference: Advanced Bash-Scripting Guide.

参考:高级 Bash 脚本指南

回答by Anthony Rutledge

Knowledge of high level programming languages (C/C++/Java/PHP/Python/Perl ...) would suggest to the layman that bash functions should work like they do in those other languages. Instead, bash functions work like shell commands and expect arguments to be passed to them in the same way one might pass an option to a shell command (e.g. ls -l). In effect, function argumentsin bash are treated as positional parameters($1, $2..$9, ${10}, ${11}, and so on). This is no surprise considering how getoptsworks. Do not use parentheses to call a function in bash.

高级编程语言(C/C++/Java/PHP/Python/Perl ...)的知识会向外行建议 bash 函数应该像在其他语言中一样工作。相反,bash 函数的工作方式类似于 shell 命令,并期望以与将选项传递给 shell 命令(例如ls -l)相同的方式将参数传递给它们。实际上,bash 中的函数参数被视为位置参数$1, $2..$9, ${10}, ${11},等等)。考虑到getopts工作原理,这并不奇怪。不要使用括号在 bash 中调用函数。



(Note: I happen to be working on Open Solaris at the moment.)

注意:我目前正在开发 Open Solaris。)

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


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


# In the actual shell script
# 
declare filename= # declare gives you more options and limits variable scope
backupWebRoot ~/public/www/ webSite.tar.zip

Want to use names for variables. Just do this.

想为变量使用名称。就这样做。

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

Want to pass an array to a function?

想要将数组传递给函数?

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

Inside the function, handle the arguments like this.

在函数内部,像这样处理参数。

function linearSearch ()
{
    declare myVar=""

    shift 1 # removes  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[@]}"

Need to pass a value and an array, but still use "$@" inside the function?

需要传递一个值和一个数组,但仍然在函数内部使用“$@”?

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

回答by niieani

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

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:

您还可以将参数注释为 @required 或 @readonly,创建 ...rest 参数,从顺序参数创建数组(使用 eg string[4])并可选择在多行中列出参数:

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+=( "" )
      shift
    done

    local declaration=
    local wrapLeft='"'
    local wrapRight='"'
    local nextType=""
    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=""

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

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).

换句话说,您不仅可以通过名称调用参数(这构成了更具可读性的核心),您实际上还可以传递数组(以及对变量的引用——尽管此功能仅适用于 bash 4.3)!另外,映射的变量都在本地范围内,就像 $1(和其他)一样。

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.

使这项工作的代码非常简单,并且可以在 bash 3 和 bash 4 中运行(这些是我测试过的唯一版本)。如果您对更多这样的技巧感兴趣,这些技巧使使用 bash 开发变得更好更容易,您可以查看我的Bash Infinity Framework,下面的代码可作为其功能之一。

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

回答by niieani

Miss out the parens and commas:

错过括号和逗号:

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

and the function should look like this:

该函数应如下所示:

#!/bin/bash

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

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

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

add x y #feeding the arguments

回答by Milad P.

I hope this example can help you. It takes two numbers from the user, feeds them to the function called add(in the very last line of the code), and addwill sum them up and print them.

我希望这个例子可以帮助你。它从用户那里获取两个数字,将它们提供给调用的函数add(在代码的最后一行),并将add它们相加并打印出来。

#!/bin/bash
echo "parameterized function example"
function print_param_value(){
    value1="" #  represent first argument
    value2="" #  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 "" "" #parameter  and  during executing

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

回答by Adiii

A simple example that will clear both during executing script or inside script while calling a function.

一个简单的例子,它将在执行脚本期间或在调用函数时清除脚本。

#!/bin/bash
function myBackupFunction(){ # directory options destination filename
local directory="" options="" destination="" filename="";
  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];

回答by Wil

Thought I'd pipe in with mention of another way to pass named parameters to bash... passing by reference. This is supported as of bash 4.0

我想我会提到另一种将命名参数传递给 bash 的方法......通过引用传递。这是从 bash 4.0 开始支持的

##代码##

An alternative syntax for bash 4.3 is using a nameref

bash 4.3 的另一种语法是使用nameref

Although the nameref is a lot more convenient in that it seamlessly dereferences, some older supported distros still ship an older versionso I won't recommend it quite yet.

尽管 nameref 更方便,因为它可以无缝取消引用,但一些受支持的较旧发行版仍然提供较旧版本,因此我还不会推荐它。