Bashシェルスクリプトでは、関数は特定の結果を得るために一連の命令をグループ化する方法です。関数はミニスクリプトと考えることができます。一部のプログラミング言語では、関数はプロシージャおよびメソッドとも呼ばれます。関数は、モジュール性と再利用性を実現するための優れた方法です。
この記事では、Linuxのbashスクリプトで関数を使用する方法を例を挙げて説明します。この記事の終わりまでに、bash関数の使用にかなり慣れることができます。
Bashで関数を定義する方法
関数を操作するときに理解しなければならない重要なことが2つあります。
- 関数の定義
- 関数の呼び出し。
bashスクリプトを作成して実行する方法と同様に、関数を定義し、関数を実行するために呼び出す必要があります。
bashで関数を定義する構文上の方法は2つあります。最初の方法は、bashの組み込みキーワード"function"
を使用することです。 関数の名前が続きます。コードのブロックは、中括弧{}
内に記述されます。 。
function [name] {
Block of code
}
2番目の方法は、キーワード"function"
を使用せずに関数を作成することです。 。関数名から始めて、角かっこを続けます。
[name](){
Block of Code
}
どれを選ぶ?まあ、それは常に個人的な選択です。どちらかを選択しても欠点はありません。
コンパクト関数と呼ばれる単一行関数を作成することもできます。 。コンパクトな関数では、中括弧内のコードの各行はセミコロン(;
)で区切られます。 ) 。
ターミナルを起動し、マルチライン関数を記述します。上矢印キーを押すと、複数行で書き込んだものがすべてコンパクトな関数として変換されることがわかります。
[name](){ first_line; second_line; }
ベストプラクティス:
- いずれか1つの構文を選択し、それと一致するようにしてください。
- コラボレーション環境で作業している場合は、コーディング時に全員が同じ標準を維持することが重要です。
命名規則
関数を作成するときは、関数に名前を付ける必要があります。関数名はわかりやすく、他の関数、変数、定数などですでに使用されている名前は避けてください。「スネークケース」 関数に名前を付けるための推奨される方法です。スネークケースの場合、単語はアンダースコアで区切られます。
以下の例を見てください。 "hello_world"
hello worldをstdout(ターミナル)に出力するだけのスネークケーススタイル。
hello_world() { echo "Running Simple Hello World Function" } hello_world
Bashで関数を呼び出す方法
"log_cleanup"
という名前の簡単なクリーンアップ関数を作成しましょう 。この関数の目的は、".log"
を削除することです。 30日より古いファイル。
log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs/ -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" }
関数は定義されていますが、関数がその仕事をするのに十分でしょうか?絶対違う。関数を実行するには、関数を呼び出す必要があります。
関数を呼び出すには、関数定義の後に関数名を入力するだけです。
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" } # Calling the function log_cleanup
関数定義の前に関数を呼び出そうとすると、次のエラーが発生します。
line 3: log_cleanup: command not found
なぜそうなのか?スクリプトを実行すると、コードは上から下に1行ずつ解釈されます。関数を読み取り、bash環境(メモリ)にロードします。ただし、ここでは、インタプリタが関数を読み取ってその環境にロードする前に、関数を呼び出しています。
別の関数の内部から関数を呼び出す場合、関数定義は最初の関数を除いて任意の順序にすることができます。下の画像を見てください。関数func2 func1から呼び出されます およびfunc3 func2から呼び出されます それらの定義の前に。しかし、 func1 最初に定義されてから呼び出されます。 func1までに と呼ばれ、すべての関数定義はすでに解釈され、環境にロードされています。
終了ステータスと戻り値
すべてのLinuxコマンドは、終了ステータス(0〜255)を返します。ゼロは成功したと言われ、残りの終了コードは異なる意味の失敗であると言われます。同様に、関数を実行すると、関数内の最後の実行コマンドの終了ステータスも返されます。
同じ「クリーンアップ」機能をもう一度実行させてください。しかし、自分のマシンでは使用できないパスを指定したので、find
コマンドは失敗します。 $?
を使用しています 画像に示されているように、スクリプト内の終了ステータスを取得します。
Running Cleanup On Older Logs - 30 days find: '/home/karthick/Documents/Projectss/logs': No such file or directory Cleanup Completed Exit status of function log_cleanup is ⇒ 0
関数から返される終了ステータスは、echo
からのものです。 関数内の最後のコマンドとして実行されたコマンド。これはあなたが期待するかもしれない振る舞いではありません。
この動作を克服するには、bashに組み込まれている"return"
を使用できます。 ステートメント。
$ type -a return
return is a shell builtin
Returnは整数[N]値を受け入れ、関数を終了して、呼び出し元(関数)に戻り値を渡します。 returnステートメントを使用する前に、returnステートメントの使用方法に関するいくつかのルールを理解する必要があります。前に述べたように、returnは0から255までの整数値を受け入れます。引数(整数値)が渡されない場合、または値が255を超える場合、returnステートメントは最後に実行されたコマンドの終了ステータスを使用します。
リターンを使用して"cleanup"
を修正します 関数の動作。ここでは、returnコマンドとともに条件ステートメントを使用しています。
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "[ INFO ] - Running Cleanup On Older Logs - 30 days" if [[ -d "/home/karthick/Documents/Projectss/logs" ]] then find -name "*.log" -type f -mtime +30 -delete echo "[ SUCCESS] - Cleanup Completed" else echo "[ ERROR ] - Directory path wrong... Cleanup has not happened..." return 1 fi } # Calling the function log_cleanup echo "++ Exit status of log_cleanup function is ==> $?"
以下の出力を見てください。関数は終了コード1を返します returnステートメントから。
[ INFO ] - Running Cleanup On Older Logs - 30 days
[ ERROR ] - Directory path wrong… Cleanup has not happened…
++ Exit status of log_cleanup function is ==> 1
関数への引数の受け渡し
bashスクリプトに引数を渡すのと同様に、関数も引数を受け入れます。紛らわしいのは、関数が同じ$1
を使用することです。 …$9
引数をスクリプトに渡すのと同じ、引数にアクセスするための特別な変数。この特別な変数を関数の内外で使用するとどうなるかを理解する必要があります。
cat > arg_test.sh #!/bin/bash echo "Value passed in \$1 is = $1" howdy(){ echo "value of \$1 inside function is = $1" } howdy # Function Call
上記のスニペットをコピーして実行し、違いを確認してください。文字列"Howdy"
スクリプトの最初の引数として渡されます。
$ ./arg_test.sh howdy
Value passed in $1 is = howdy
value of $1 inside function is =
出力から、$1
を確認できます。 $1
のため、関数内は空の値を出力しています 関数内は$1
とは異なります 同じ名前を共有していますが、関数の外にあります。
関数に引数を渡すには、関数名の後にスペースを残し、次の図に示すように引数を渡します。スペースで区切られた各引数には、それぞれの変数$1
が割り当てられます。 …$N
関数内でこの変数を使用して引数を処理できます。
log_cleanup $1 $2 ….. $N
上のスクリーンショットにあるように、ディレクトリ名と日数を引数として渡しています。
関数の変数スコープ
関数内または関数外で変数を作成すると、グローバルにアクセスできます。デフォルトでは、変数はグローバルスコープで作成されます。
以下の例を見てください。両方の変数outside_function
にアクセスしようとした場合 およびinside_function
、それらの値にアクセスできます。これは、関数が実行されて終了した場合でも、関数内で作成された変数にグローバルにアクセスできることを意味します。
#!/bin/bash outside_function="This variable is from outside the function" func1(){ inside_function="This variable is from inside the func1" } func1 echo $outside_function echo $inside_function
一部のプログラミング言語では、これは動作ではない場合があり、関数内で作成された変数は、関数の実行時に使用可能になります。しかし、bashでは動作が異なります。
変数を関数に対してローカルにするには、bash組み込みの"local"
を使用できます。 キーワード。 localキーワードは、変数スコープをグローバルからローカルに制限し、変数は関数の実行時にのみアクセスできます。
#!/bin/bash outside_function="This variable is from outside the function" func1(){ local inside_function="This variable is from inside the func1" } func1 echo $outside_function echo $inside_functionの内部からのものです
推奨される読み物:
- Bashスクリプティング–例で説明されている変数
localキーワードを使用すると、異なる関数で同じ変数名を使用できます。
ヘッズアップ: 変数、関数、bashキーワードとしてすでに使用されている識別子の使用は常に避けてください。上記の例は、動作を理解するためだけに示されています。
モジュール性と信頼性
関数の理解と書き込みは短時間で実行できます。しかし、優れた関数を作成するには、環境をよりよく理解するのに時間がかかります。導入セクションですでに指摘したように、bash関数を使用すると、モジュール性と再利用性を大幅に向上させることができます。
例を見てみましょう。 20個のスクリプトを作成し、各スクリプトにlog_cleanup
を含めました。 前のセクションでハウスキーピングタスクを実行するために見た機能。この関数を20個のスクリプトすべてに含める代わりに、単一の関数定義を作成して20個のスクリプトにインポートできます。このようにして、モジュール性と再利用可能な機能を実現しています。これはインポートに似ています Pythonのステートメント、 include Cなどのステートメント
下の画像をご覧ください。 script1.sh
という名前の2つのスクリプトを作成しました およびscript2.sh
およびlog_cleanup
関数はcleanup.sh
という名前の別のファイルに書き込まれます 。
source
を実行して関数をインポートしています 指図。 source
コマンドは、引数として渡されたファイルを実行し、変数または関数を現在のbashセッションにロードします。このようにlog_cleanup
を実行すると 別のスクリプトファイルから、関数はすでに現在の環境にロードされており、アクセス可能です。
上の画像から、引数がどのように役立つかを理解できます。関数の定義は1つだけであり、ユースケースに応じて、さまざまな引数やさまざまなスクリプトを受け入れるように関数を変更できます。
ヘッズアップ: source
を使用してシェルスクリプトを実行することもできます スクリプトを実行するためのサブシェルを作成する代わりに、現在のシェルでスクリプトを実行するコマンド。
結論
このガイドでは、Bash関数と、スクリプトで関数を定義して呼び出す方法について例を挙げて説明しました。関数に慣れるためには、さまざまなユースケースで関数を練習する必要があります。ご質問やご意見がございましたら、下のコメントセクションからお気軽にお知らせください。
関連記事:
- Bashスクリプティング–例で説明されているForループ
- Bashスクリプティング–ループの説明中およびループまで
- エクスポートがある場合とない場合のBash変数の定義の違い
- Linuxの例で説明されているBashEchoコマンド
- 初心者向けのBashヒアドキュメントチュートリアル
- 例を使用して説明されたBashリダイレクト