0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

bash の関数定義の本体は { ... } や ( ... ) などの Compound Commands

Last updated at Posted at 2022-12-28

bash で関数を定義するときに function name { ... } 以外に function name ( ... ) と書くことができると知りました。

bash のマニュアル (Bash Reference Manual) を参照したところ、関数の本体は compound-command と定義されており、他の書き方もできることが分かりました。

bash の関数定義

bash では、関数を定義する構文が 2 種類あります。どちらの構文であっても、関数の本体は compound-command です。

Bash Reference Manual > 3.3 Shell Functions より引用:

Functions are declared using this syntax:

fname () compound-command [ redirections ]

or

function fname [()] compound-command [ redirections ]

bash の compound-command

compound-commandBash Reference Manual > 3.2.5 Compound Commands で説明されているとおり、Looping Constructs, Conditional Constructs, Grouping Commands のいずれかです。

  • Looping Constructs ... for, while, until
  • Conditional Constructs ... if, case, [[ expression ]] など
  • Grouping Commands ... ( ... ), { ... }

Looping Constructs の使用例

Looping Constructs を用いると、関数定義を次のように書き換えることができます。

# before
function f
{
    for x in 1 2 3
    do  
        echo $x
    done
}
# after
function f
    for x in 1 2 3
    do  
        echo $x
    done

Conditional Constructs の使用例

Conditional Constructs を用いると、関数定義を次のように書き換えることができます。

# before
function f
{
    case "$1" in
        1)  
            echo "one"
            ;;
        2)  
            echo "two"
            ;;
        *)  
            echo "many"
            ;;
    esac
}
# after
function f
    case "$1" in
        1)
            echo "one"
            ;;
        2)
            echo "two"
            ;;
        *)
            echo "many"
            ;;
    esac

Grouping Commands の使用例

Grouping Commands には current-shell で実行される { ... } と sub-shell で実行される ( ... ) があります。( ... ) を用いると、意図せず current-shell の状態 (変数やカレントディレクトリなど) を変更してしまう心配が無くなります。

function f1
{
    x=777
    cd /tmp
}

# グローバル変数 x とカレントディレクトリを変更してから f1 を呼び出す.
# f1 の本体は current-shell で実行されるため "x=777, pwd=/tmp" が出力される.
x=123 && cd / && f1
echo "x=$x, pwd=$(pwd)" # => "x=777, pwd=/tmp"
function f2
(
    x=777
    cd /tmp
)

# グローバル変数 x とカレントディレクトリを変更してから f2 を呼び出す.
# f2 の本体は sub-shell で実行されるため "x=123, pwd=/" が出力される.
x=123 && cd / && f2
echo "x=$x, pwd=$(pwd)" # => "x=123, pwd=/"

どの形式で関数を定義すべきか

ここまでの内容を踏まえて、bash の関数定義はどの書き方をすると良いのでしょうか。

積極的な理由がない限り function name { ... } 形式に統一すると良いと思います。理由は、他の形式を目にする機会が少ない (パッと見た時にバグの可能性を疑ってしまう) ためです。

# NG
function f
    for x in 1 2 3
    do
        echo $x
    done

# OK
function f
{
    for x in 1 2 3
    do
        echo $x
    done
}
# NG
function f
    case "$1" in
        ...
    esac

# OK
function f
{
    case "$1" in
        ...
    esac
}
# NG
function f
(
    ...
)

# OK
function f
{
    (
        ...
    )
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?