関数定義はコマンドです。関数定義を実行すると、関数本体が一重引用符で囲まれているように、関数本体はそのまま維持されると思いました。
私はから次のことを理解したとき、私は、私が間違っていた知っていたバッシュマニュアルでG-男の答えに私のエイリアスと関数の質問:
エイリアスは、関数の実行時ではなく、関数定義の読み取り時に展開されます…。
したがって、次の例に示すように、エイリアス展開は関数本体で実行されますが、パラメータ展開は実行されません。
$ alias myalias=cat
$ echo $var
3
$ myfunc() { myalias myfile; echo $var; }
$ declare -fp myfunc
myfunc ()
{
cat myfile;
echo $var
}
同様に、関数の呼び出しもコマンドです。
関数で定義されたエイリアスは、その関数が実行されるまで使用できません。
したがって、エイリアス定義は、関数定義の実行時ではなく、実行時、つまり関数の呼び出し時にのみ実行されます。
エイリアスの拡張とエイリアス定義の実行は、以下にリストされているシェル操作の2つにすぎません。
私の質問は次のとおりです。
関数本体内で実行されるシェル操作と実行されない操作、
関数定義を実行するとき?
関数を呼び出すとき、つまり関数を実行するとき?
関数の定義の実行と関数の呼び出しの両方で実行されるシェル操作はありますか?
または、関数の定義を実行して関数を呼び出すと、重複しないシェル操作のセットが実行されますか?
可能な操作は、Bashマニュアルからの次の引用にリストされています。
3.1.1シェル操作
以下は、シェルがコマンドを読み取って実行するときのシェルの動作の簡単な説明です。基本的に、シェルは次のことを行います。
ファイル(39ページのセクション3.8 [シェルスクリプト]を参照)、
-c
呼び出しオプションの引数として指定された文字列(80ページのセクション6.1 [Bashの呼び出し]を参照)、またはユーザーの端末から入力を読み取ります。ブレークセクション3.1.2に記載し引用ルールに従う単語やオペレータに入力、[引用]、6ページこれらのトークンは、メタキャラクタによって分離されます。エイリアスの拡張は、この手順で実行されます(88ページのセクション6.6 [エイリアス]を参照)。
トークンを単純なコマンドと複合コマンドに解析します(8ページのセクション3.2 [シェルコマンド]を参照)。
さまざまなシェル拡張(21ページのセクション3.5 [シェル拡張]を参照)を実行し、拡張されたトークンをファイル名のリスト(30ページのセクション3.5.8 [ファイル名拡張]を参照)とコマンドおよび引数に分割します。
必要なリダイレクトを実行し(31ページのセクション3.6 [リダイレクト]を参照)、引数リストからリダイレクト演算子とそのオペランドを削除します。
コマンドを実行します(35ページのセクション3.7 [コマンドの実行]を参照)。
オプションで、コマンドが完了するのを待ち、その終了ステータスを収集します(38ページのセクション3.7.5 [終了ステータス]を参照)。
<rant>
「関数定義の実行」と「関数定義の実行」は一般的なイディオムではありません。ほとんどの人はそれを単に「関数の定義」と呼ぶだろうと思います。OK、そのフレーズは参照するように解釈されるかもしれません
- 関数の特性とインターフェース(パラメーターとその他の入力、処理、および出力)を概念的に指定します(これは、個人または人々のグループによって実行されるアクティビティです)。
- 関数の実装を選択する。つまり、関数本体で使用するコマンド。これは、おそらく紙、ホワイトボード、および/または黒板を使用して、個人または人々のグループによって実行されるアクティビティです。
- 関数の実装をテキストエディタに入力するか、インタラクティブシェルに直接入力します(これはもちろん、人、または場合によっては人々のグループ、あるいは非常にインテリジェントで器用な猫、犬、猿によって実行されるアクティビティでもあります) )
上記との混同を恐れる場合は、「関数定義の読み取り」や「関数の定義の処理」などのフレーズを使用した方がよい場合があります。
「関数定義はコマンドです」とあなたは言います。そのような主張が何を意味するのかは明らかではありません—それは意味論の問題です—しかし、意味論レベルでは、それは議論の余地があります。 Bashマニュアル(シェルコマンド)のセクション3.2には、単純コマンド、パイプライン、リスト、複合コマンド、コプロセス、およびGNUParallelの6種類のシェルコマンドがリストされています。関数定義は、これらのカテゴリのいずれにもうまく適合しません。
</ rant>
あなたの質問に行き、7つのステップ/操作を見て、
トークンの解析。これは、シェルが単純なコマンドではなく関数定義を調べていることを認識するために、少なくとも「関数の定義の処理」フェーズ中に開始する必要があります。それを超えて、この簡単な実験を行うことができます。シェルに次のいずれかを入力します。
myfunc1() { myfunc2() {
< or ;
} }
を入力する前に、「構文エラー」で失敗します}
。(>
そして&
同じ効果を生み出します。)したがって、明らかにこのステップは関数の定義の処理の一部です。
echo $var
(そうあるべきですがecho "$var"
、それは別の問題です)をに変更しecho *
ます。
echo *
されており、展開されていないことがわかります。cd
)および/またはファイルの作成および/またはファイルの削除および/またはファイルの名前の変更を行ってから、関数を呼び出し(実行)します。現在のディレクトリにあるファイル1の現在のリストを出力し、関数を定義したディレクトリの内容を反映していないことがわかります。echo $var
しecho hello > myfile
ます。
> myfile
。myfile
まだ作成されていないことがわかります。言い換えれば、@ ilkkachuが言ったこととまったく同じです。
私が考えることができる1つの例外的な特殊なケースは、関数にeval
ステートメントが含まれている場合、関数の実行時にステップ2と3(字句解析と構文解析)が(再び)発生することです。しかし、それはあなたの質問が実際に求めている範囲外だと思います。 。
____________
1隠し(ドット)ファイルを除くshopt -s dotglob
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加