サーチ…


構文

  • functionキーワードを使用して関数を定義する:

    function f {
    

    }

  • 関数を()定義する:

    f(){
    

    }

  • functionキーワードと()両方を持つ関数を定義します。

    function f(){
    

    }

シンプルファンクション

helloWorld.sh

#!/bin/bash

# Define a function greet
greet ()
{
    echo "Hello World!"
}

# Call the function greet
greet

スクリプトを実行すると、メッセージが表示されます

$ bash helloWorld.sh
Hello World!

関数を使ってファイルをソーシングすると、現在のbashセッションでファイルを利用できることに注意してください。

$ source helloWorld.sh   # or, more portably, ". helloWorld.sh"
$ greet
Hello World!

いくつかのシェルで関数をexport 、子プロセスに公開することができます。

bash -c 'greet'  # fails
export -f greet  # export function; note -f
bash -c 'greet'  # success

引数を持つ関数

helloJohn.sh

#!/bin/bash

greet() {
  local name="$1"
  echo "Hello, $name"
}

greet "John Doe"
# running above script
$ bash helloJohn.sh
Hello, John Doe
  1. どのような方法でも引数を変更しない場合は、それをlocal変数にコピーする必要はありません。単にecho "Hello, $1"ます。

  2. $1$2$3などを使用して、関数内の引数にアクセスすることができます。

    注意:引数が9 $10以上の場合は動作しません(bashは$ 1 0として読み込みます)。 ${10}${11}などを実行する必要があります。

  3. $@は関数のすべての引数を参照します:

    #!/bin/bash
    foo() {
      echo "$@"
    }
    
    foo 1 2 3 # output => 1 2 3
    

    注意:ここのように、実際には必ず"$@"前後に二重引用符を使用してください。

    引用符を省略すると、シェルはワイルドカードを展開します(ユーザがそれを避けるために特に引用した場合でも)。そして、一般的に望ましくない動作や潜在的なセキュリティ問題を引き起こします。

    foo "string with spaces;" '$HOME' "*"
    # output => string with spaces; $HOME *
    
  4. デフォルトの引数は${1:-default_val}です。例えば:

    #!/bin/bash
    foo() {
      local val=${1:-25}
      echo "$val"
    }
    
    foo     # output => 25
    foo 30  # output => 30
    
  5. 引数を必要とする${var:?error message}

    foo() {
      local val=${1:?Must provide an argument}
      echo "$val"
    }
    

関数からの戻り値

Bashのreturn文はC-関数のような値を返しませんが、代わりに戻り状態の関数を終了します。その関数の終了ステータスと考えることができます。

関数から値を返す場合は、次のようにstdout値を送ります:

fun() {
    local var="Sample value to be returned"
    echo "$var"
    #printf "%s\n" "$var"
}

今、もしあなたが:

var="$(fun)"

funの出力は$var格納されます。

フラグとオプションのパラメータの処理

getopts組み込み関数は、関数内で使用して、フラグとオプションのパラメーターを収容する関数を記述することができます。これは特別な困難はありませんが、 getoptsが扱う値を適切に処理する必要があります。例として、 stderrにメッセージを書き込み、コード1またはパラメータとして-xオプションに指定された任意のコードで終了するfailwith関数を定義します。

# failwith [-x STATUS] PRINTF-LIKE-ARGV
#  Fail with the given diagnostic message
#
# The -x flag can be used to convey a custom exit status, instead of
# the value 1.  A newline is automatically added to the output.

failwith()
{
    local OPTIND OPTION OPTARG status

    status=1
    OPTIND=1

    while getopts 'x:' OPTION; do
        case ${OPTION} in
            x)    status="${OPTARG}";;
            *)    1>&2 printf 'failwith: %s: Unsupported option.\n' "${OPTION}";;
        esac
    done

    shift $(( OPTIND - 1 ))
    {
        printf 'Failure: '
        printf "$@"
        printf '\n'
    } 1>&2
    exit "${status}"
}

この関数は次のように使用できます。

failwith '%s: File not found.' "${filename}"
failwith -x 70 'General internal error.'

等々。

printfについては 、変数を第1引数として使用しないでください。印刷するメッセージが変数の内容で構成されている場合は、 %s指定子を使用して

failwith '%s' "${message}"

関数の終了コードは、最後のコマンドの終了コードです

ホストが稼働しているかどうかをチェックするこの関数例を考えてみましょう:

is_alive() {
    ping -c1 "$1" &> /dev/null
}

この関数は、最初の関数パラメータで指定されたホストに単一のpingを送信します。 pingの出力とエラー出力はどちらも/dev/nullリダイレクトされるため、関数は何も出力しません。しかし、 pingコマンドは成功した場合には終了コード0を、失敗した場合にはゼロ以外の値を返します。これが関数の最後の(そしてこの例では唯一の)コマンドなので、 pingの終了コードは関数自体の終了コードに再利用されます。

この事実は条件文で非常に有用です。

たとえば、ホストgrauchoが起動している場合は、 ssh接続しssh

if is_alive graucho; then
    ssh graucho
fi

別の例:ホストgrauchoが起動するまで繰り返しチェックし、 ssh接続しssh

while ! is_alive graucho; do
    sleep 5
done
ssh graucho

関数定義を出力する

getfunc() {
    declare -f "$@"
}

function func(){
    echo "I am a sample function"
}

funcd="$(getfunc func)" 
getfunc func # or echo "$funcd"

出力:

func () 
{ 
    echo "I am a sample function"
}

名前付きパラメータを受け取る関数

foo() {
  while [[ "$#" -gt 0 ]]
  do
    case $1 in
      -f|--follow)
        local FOLLOW="following"
        ;;
      -t|--tail)
        local TAIL="tail=$2"
        ;;
    esac
    shift
  done

  echo "FOLLOW: $FOLLOW"
  echo "TAIL: $TAIL"
}

使用例:

foo -f
foo -t 10
foo -f --tail 10
foo --follow --tail 10


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow