プログラミングについて読んで、何度も「コールバック」という概念に触れました。
興味深いことに、私は「コールバック関数」という用語について「教訓的」または「明確」と呼ぶことができる説明を一度も見つけることができませんでした(私が読んだほとんどすべての説明は他の説明とは非常に異なるようです)。混乱)。
Bashに「コールバック」というプログラミングの概念はありますか?それでは、小さくて簡単なBashの例に答えてください。
ベストアンサー1
典型的な命令型プログラミングでは、明示的な制御フローを通じて順番に実行される一連のコマンドを作成します。たとえば、
if [ -f file1 ]; then # If file1 exists ...
cp file1 file2 # ... create file2 as a copy of a file1
fi
など。
例に示すように、命令型プログラミングでは、実行フローに非常に簡単に従うことができます。常に与えられたコード行から始まり、実行コンテキストを決定し、ユーザーが提供するすべてのコマンドが実装されることがわかります。プロセスの場所(または関数を作成する場合は呼び出しサイトの場所)。
コールバックがフローを変更する方法
コールバックを使用する場合、コマンドセットの使用を「地理的」に配置するのではなく、呼び出す必要がある時期を説明することです。他のプログラミング環境の一般的な例には、「このリソースをダウンロードし、ダウンロードが完了したらこのコールバックを呼び出す」などの状況があります。 Bashにはこれらの一般的なコールバック構造はありませんが、コールバックがあります。エラー処理たとえば、他の状況もあります(まず理解する必要があります)。コマンドの置き換えそしてスラム終了モードこの例を理解してください):
#!/bin/bash
scripttmp=$(mktemp -d) # Create a temporary directory (these will usually be created under /tmp or /var/tmp/)
cleanup() { # Declare a cleanup function
rm -rf "${scripttmp}" # ... which deletes the temporary directory we just created
}
trap cleanup EXIT # Ask Bash to call cleanup on exit
自分でやりたい場合は、上記の内容をファイルに保存してください。たとえば、cleanUpOnExit.sh
実行可能にして実行します。
chmod 755 cleanUpOnExit.sh
./cleanUpOnExit.sh
ここで私のコードはcleanup
関数を明示的に呼び出しません。 Bashにtrap cleanup EXIT
、つまり「Bashさんに、cleanup
終了するときにこのコマンドを実行してください」(cleanup
これは私が以前に定義した関数ですが、Bashが理解するすべてのものかもしれません)。 Bashは、致命的ではないすべてのシグナル、シャットダウン、コマンドの失敗、および一般的なデバッグをサポートします(各コマンドの前に実行するコールバックを指定できます)。ここで、コールバックは、cleanup
シェルが終了する前に Bash によって「コールバック」される関数です。
シェル引数をコマンドとして評価するBashの機能を活用して、コールバック指向のフレームワークを構築できます。これはこの回答の範囲をわずかに超えており、関数の配信に常にコールバックが含まれることを示唆しているため、より多くの混乱を招く可能性があります。バラよりBash:関数を引数として渡す基本機能のいくつかの例です。イベント処理コールバックと同様に、ここでのアイデアは、関数が他の関数だけでなくデータを引数として使用できることです。これにより、発信者はアクションとデータの両方を提供できます。このアプローチの簡単な例は次のとおりです。
#!/bin/bash
doonall() {
command="$1"
shift
for arg; do
"${command}" "${arg}"
done
}
backup() {
mkdir -p ~/backup
cp "$1" ~/backup
}
doonall backup "$@"
cp
(参考までに複数のファイルを処理できるため、これは少し役に立たないことがわかります。)
doonall
ここでは、引数として提供された他のコマンドを受け入れ、それを残りの引数に適用する関数を作成し、それを使用してスクリプトに指定されたすべての引数でbackup
関数を呼び出します。結果は、すべてのパラメータを1つずつバックアップディレクトリにコピーするスクリプトです。
このアプローチを使用すると、単一の責任で関数を作成できます。doonall
責任は、すべての引数に対して一度に1つずつジョブを実行することです。backup
責任は、バックアップディレクトリに対応する(唯一の)引数のコピーを作成することです。doonall
どちらbackup
も異なるコンテキストで使用できるため、より多くのコードの再利用、より良いテストなどが可能です。
この場合、コールバックは関数でbackup
あり、doonall
他のすべてのパラメータを「コールバック」するように指示します。つまり、doonall
アクション(最初のパラメータ)とデータ(残りのパラメータ)を提供します。
(2番目の例で説明したユースケースでは、「コールバック」という用語を直接使用しませんが、これは私が使用している言語からの習慣である可能性があります。関数やラムダを渡すと思います。 )。