機能定義命令だ。関数定義が実行されると、関数本文が一重引用符のようにそのまま残ると思います。
私は次のことを学んだときに間違っていたことがわかりました。バッシュマニュアル 存在するGマンの答え 私に与えられたエイリアスと機能質問:
エイリアスは、関数の実行時ではなく、関数定義を読み取るときに拡張されます。
したがって、次の例に示すように、エイリアス拡張は関数本体で実行されますが、パラメータ拡張は実行されません。
$ alias myalias=cat
$ echo $var
3
$ myfunc() { myalias myfile; echo $var; }
$ declare -fp myfunc
myfunc ()
{
cat myfile;
echo $var
}
同様に、関数呼び出しコマンドでもあります。
関数で定義されたエイリアスは、関数が実行された後にのみ使用できます。
したがって、エイリアス定義は、関数定義の実行時ではなく、実行時にのみ実行されます(つまり、関数が呼び出されたとき)。
エイリアス拡張とエイリアス定義の実行は、以下に示すシェル操作の2つに過ぎません。
私の質問は次のとおりです
関数本体内でどのシェル操作が実行され、どのアクションが実行されませんか?
いつ関数定義の実行?
いつ通話機能つまり、機能を実行する?
関数定義の実行と関数呼び出しの間でシェル操作が実行されますか?
または、関数定義を実行してその関数を呼び出すと、重複しないシェルワークセットが実行されますか?
考えられるアクションは、次の引用にリストされています。バッシュマニュアル:
3.1.1 シェル動作
以下は、コマンドの読み取りと実行時のシェルの操作の簡単な説明です。デフォルトでは、シェルは次のことを行います。
読む入力は、ファイル(39ページの3.8節「シェルスクリプト」を参照)、呼び出しオプションの引数として提供される文字列
-c
(80ページの6.1節「Bash呼び出し」を参照)、またはユーザー端末から来ます。休憩時間6ページ3.1.2項[注]で説明されている引用規則に従い、単語と演算子を入力します。これらのタグはメタ文字で区切られます。エイリアス拡張この手順を実行します(88ページのセクション6.6 [エイリアス]を参照)。
分析するトークンを単純および複合コマンドに変換します(8ページのセクション3.2「シェルコマンド」を参照)。
様々な実行シェル拡張(21ページのセクション3.5「シェル拡張」を参照)拡張タグをファイル名のリスト(30ページのセクション3.5.8「ファイル名拡張子」を参照)とコマンドと引数で除算します。
必要な処置を行ってください。リダイレクト(31ページのセクション3.6「リダイレクト」を参照)引数リストからリダイレクト演算子とそのオペランドを削除します。
実装する(35ページの3.7節「コマンドの実行」を参照)
選択科目待つコマンドが完了し、終了ステータスが収集されます(38ページのセクション3.7.5 [終了ステータス]を参照)。
答え1
<rant>
「実行関数定義」と「実行関数定義」は一般的な慣用語ではありません。私はほとんどの人がこれを単に「関数定義」と呼ぶことを期待しています。さて、このフレーズは以下を指すものと解釈することができます。
- 機能(個人またはグループが実行するアクティビティ)の特性とインタフェース(パラメータと他の入力、処理、および出力)を概念的に指定します。
- 関数の実装、つまり関数本体で使用するコマンドを選択します。これは、紙、ホワイトボード、および/または黒板を使用して1人または複数の人が実行できる活動です。
- タイプ機能をテキストエディタまたは直接インタラクティブシェルに実装します(もちろん返品個人または複数の人が行う活動、または非常にインテリジェントでアジャイルな猫、犬またはサルが行う活動)
上記と混同されるのではないかと心配している場合は、「関数定義の読み取り」、「関数定義の処理」などのフレーズがより良い可能性があります。
「関数定義は命令です」と言われましたが、これが何を意味するのかは明らかではありません。意味論の問題ですが、意味論的レベルでは議論の余地があります。 Bashマニュアルセクション3.2(シェルコマンド) 6つのシェルコマンド(単純コマンド、パイプ、リスト、複合コマンド、コプロセス、およびGNUパラレル)が一覧表示されます。関数定義は、これらのカテゴリには適していません。
</rant>
あなたの質問に答えるために7つのステップ/アクションを見てください。
- 入力の読み取りは明らかに以前に行わなければなりません。何もないそうしないと、これが発生する可能性があります。これは再び意味論の問題です。ファイルまたは他のストリーミングテキストソースから入力を読み取ることが「関数定義の読み取り」の一部であるか、または「関数定義の処理」の前提条件/前奏曲と呼ばれることがあります。
- 入力を単語と演算子に分割することは、明らかに「関数定義処理」の一部です。
- もちろん、入力をトークンに分解するのは前提条件/前奏曲です。分析するトークン(以下のステップ3)。
- マニュアルには、「このステップでエイリアス拡張が実行されます」と記載されており、関数定義を読み取るとエイリアス拡張が発生することがわかっていることを質問に示します。
マークアップを解析します。これは、少なくとも「プロセス機能の定義」ステップで開始する必要があります。気づく単純なコマンドではなく、機能定義を見てください。それ以外の場合は、次の簡単な実験を実行できます。次のいずれかをシェルに入力します。
myfunc1() { myfunc2() { < or ; } }
(
}
そして同じ効果を>
生み出します。)明らかに、このステップは関数定義を処理するプロセスの一部です。&
- 呼び出し機能の一部として、さまざまなシェル拡張が実行されます。
- 質問にパラメータ拡張について知っていることを示しました。確かに発生する 関数定義を読むとき。
- 関数定義を読み取るときにパス名/ファイル名拡張が発生しないことを証明することも同様に簡単です。あなたの例では
echo $var
(でなければなりecho "$var"
ませんが、他の話です)をに変更してくださいecho *
。- 関数定義を見ると、まだ表示され、
echo *
拡張されていないことがわかります。 - ディレクトリ変更(
cd
)および/またはファイルの作成および/またはファイルの削除および/またはファイル名の変更後に関数を呼び出し(実行)します。出力されるのがわかります現在の現在ディレクトリにあるファイル1のリストであり、関数が定義された時点のディレクトリの内容を反映しません。
- 関数定義を見ると、まだ表示され、
- リダイレクトを実行するのはこの関数呼び出しの一部です。これも確認しやすいです。あなたの例で
echo $var
はに変更してくださいecho hello > myfile
。- 関数定義を見ると、まだとして表示されることがわかります
> myfile
。 - ディレクトリを確認すると、
myfile
まだ作成されていないことがわかります。
- 関数定義を見ると、まだとして表示されることがわかります
- コマンドの実行 – 必ず尋ねる必要がありましたか?
- コマンドを実行する前にコマンドが完了するのを待つことはできないため(ステップ6)、関数が呼び出されたときにのみこれを実行してください。
つまり、@ilkkachuの言う通り。
私が考えることができる特別な例外の1つは、関数にeval
ステートメントが含まれている場合、関数が実行されると、ステップ2と3(語彙分析と構文解析)が(再び)発生することです。しかし、これはあなたの質問が実際に要求する範囲を超えていると思います。
____________ 1指定しない限り、隠し(ドット)ファイルは含まれません
。shopt -s dotglob