以下で宣言された関数を呼び出す


15

以下でbashで宣言されている関数を呼び出すことは可能ですか?

if [ "$input" = "yes" ]; then
    YES_FUNCTION
elif [ "$input" = "no" ]; then
    NO_FUNCTION
else
    exit 0;
fi

YES_FUNCTION()
{
  .....
  .....
}

NO_FUNCTION()
{
  .....
  .....
}

回答:


36

他の人が言ったように、あなたはそれをすることはできません。

ただし、メインプログラムがファイルの先頭にあり、他の関数が以下に定義されるようにコードを1つのファイルに整理する場合は、別の main関数ます。

例えば

#!/bin/sh

main() {
    if [ "$1" = yes ]; then
        do_task_this
    else
        do_task_that
    fi
}

do_task_this() {
    ...
} 
do_task_that() {
    ...
} 

main "$@"; exit

mainファイルの最後で呼び出すと、すべての関数が既に定義されています。明示的に渡す"$@"ためにmain機能的に目に見えるスクリプトのコマンドライン引数を行う必要があります。

exitmainの呼び出しと同じ行での明示的な指定は必須ではありませんが、スクリプトファイルが変更された場合に実行中のスクリプトが混乱するのを防ぐために使用できます。これがないと、シェルはmain戻り後もスクリプトファイルからコマンドを読み続けようとします。(実行前にシェルスクリプト全体を読み取る方法を参照してください


@ikkachuは動作するはずだと思います。
msp9011

7
Bashスクリプト[[ ${BASH_SOURCE[0]} = "$0" ]] && Main "$@"では、Main実行せずに別のスクリプトでソースできるように、メイン関数を呼び出すためによく使用します。次に、関数を再利用するか、テストを作成してチェックします。
ブラックジャック

11
を持つmain "$@"; exit(とexit同じ行にmain)ことは、解釈中にファイルが変更されるのを防ぐためにも役立ちます。
ステファンシャゼラス

2
@JoL、読み取られたものは再び読み取られず、シェルはループのテキスト全体を読み取って解析してから実行を開始する必要がありますが、ループが戻った後、ファイルの残りの部分から読み取りを続行します現在の位置(およびファイルが変更されている場合は、問題が発生します)すべてが関数内にある場合、シェルは、戻り後にファイルから再び何も読み込まないことを確認するのexitと同じ行に置くと、何かを実行する前にすべてを読み取る必要があります(これらの関数の定義を除く)。mainmain
ステファンシャゼル

1
@MontyHarder、を使用するかmain; exitmain; exit $?またはを使用するかは問題ではありません。main <EOF>すべての場合main、スクリプトの終了コードとしての終了コードが使用されます。これexitは、実行中に誰かがスクリプトを編集した場合に物事が台無しになるのを防ぐためです。
-ilkkachu

13

いいえ、関数はそれらを呼び出すときにシェル環境に存在する必要があります。

Googleの「シェルスタイルガイド」には、これに対する修正があります。

呼び出される関数mainは、少なくとも1つの他の関数を含むのに十分な長さのスクリプトに必要です。

スクリプトの最後で、すべての関数の後、関数内にない唯一のステートメントとして、次のようになります。

main "$@"

これによりmain、スクリプトに指定されたパラメーターで関数が呼び出されます。main関数はスクリプトの先頭に配置することができる(スタイルガイドを一番下にそれを置くことを言いますが、その後、再び、それは多くのことを言います)。

シェルがmain呼び出しに到達すると、スクリプト内のすべての関数が解析されているため、main関数内から呼び出すことができます。


9

いいえ、関数を使用する前に宣言する必要があります。シェルスクリプトは1行ずつ読み取られ、1行ずつ実行されます。そのため、関数は宣言が実行されるまで存在しません。


あなたは正しい。問題は、スクリプトに30以上の関数があることです。コードを読むときは非常に注意が必要です。でC、それは快適です。
msp9011

3
関数宣言を別のファイルに入れて、ソースにすることができます(. yourfile)。
スティーブンキット

はい、私はそれを試しましたが、要件は単一のスクリプトを持つことです。
msp9011

@SivaPrasathまさに問題は何ですか?すべての関数を定義するだけで、メインコードを関数に入れることもできます。最後の行には、どの関数が呼び出され、スクリプトの主要部分が含まれているかが示されます。
ブラックジャック

@SivaPrasath Cではif、関数の外部にむき出しのステートメントはありません。関数は、-を含む関数を宣言するifとき、呼び出すときに定義する必要はありません。
-chepner

4

シェルには次の概念はありません declaring関数。したがって、前方宣言はできません。

結果として、シェルを呼び出す前に、シェルによって関数実装を読み取らせる必要があります。


4
技術的には、一部のシェル(ksh、zsh)には、何らかの形式の宣言(関数を宣言するが、その本体は最初の呼び出し時にのみロードされる)として見ることができる関数自動ロード機能があります。ただし、OPには適用されません。autoload fbash
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.