関数定義を実行するとき、および関数を呼び出すときに、関数本体内で実行されるシェル操作は次のうちどれですか?

ティム

関数定義はコマンドです。関数定義を実行すると、関数本体が一重引用符で囲まれているように、関数本体はそのまま維持されると思いました。

私はから次のことを理解したとき、私は、私が間違っていた知っていたバッシュマニュアルG-男の答えに私のエイリアスと関数の質問:

エイリアスは、関数の実行時ではなく、関数定義の読み取り時に展開されます…。

したがって、次の例に示すように、エイリアス展開は関数本体で実行されますが、パラメータ展開は実行されません。

$ alias myalias=cat
$ echo $var
3
$ myfunc() { myalias myfile; echo $var; }
$ declare -fp myfunc
myfunc () 
{ 
    cat myfile;
    echo $var
}

同様に、関数の呼び出しもコマンドです。

関数で定義されたエイリアスは、その関数が実行されるまで使用できません。

したがって、エイリアス定義は、関数定義の実行時ではなく、実行時、つまり関数の呼び出し時にのみ実行されます。

エイリアスの拡張とエイリアス定義の実行は、以下にリストされているシェル操作の2つにすぎません。

私の質問は次のとおりです。

  1. 関数本体内で実行されるシェル操作と実行されない操作、

    • 関数定義を実行するとき

    • 関数を呼び出すとき、つまり関数を実行するとき

  2. 関数の定義の実行と関数の呼び出しの両方で実行されるシェル操作はありますか?

    または、関数の定義を実行して関数を呼び出すと、重複しないシェル操作のセットが実行されますか?

可能な操作は、Bashマニュアルからの次の引用にリストされています

3.1.1シェル操作

以下は、シェルがコマンドを読み取って実行するときのシェルの動作の簡単な説明です。基本的に、シェルは次のことを行います。

  1. ファイル(39ページのセクション3.8 [シェルスクリプト]を参照)、-c呼び出しオプションの引数として指定された文字列(80ページのセクション6.1 [Bash呼び出し]を参照)、またはユーザーの端末から入力を読み取ります

  2. ブレークセクション3.1.2に記載し引用ルールに従う単語やオペレータに入力、[引用]、6ページこれらのトークンは、メタキャラクタによって分離されます。エイリアスの拡張は、この手順で実行されます(88ページのセクション6.6 [エイリアス]を参照)。

  3. トークンを単純なコマンドと複合コマンドに解析します(8ページのセクション3.2 [シェルコマンド]を参照)。

  4. さまざまなシェル拡張(21ページのセクション3.5 [シェル拡張]を参照)を実行し、拡張されたトークンをファイル名のリスト(30ページのセクション3.5.8 [ファイル名拡張]を参照)とコマンドおよび引数に分割します。

  5. 必要なリダイレクトを実行し(31ページのセクション3.6 [リダイレクト]を参照)、引数リストからリダイレクト演算子とそのオペランドを削除します。

  6. コマンドを実行します(35ページのセクション3.7 [コマンドの実行]を参照)。

  7. オプションで、コマンドが完了するのを待ち、その終了ステータスを収集します(38ページのセクション3.7.5 [終了ステータス]を参照)。

G-Manは「モニカを復活させる」と言います

<rant>
「関数定義の実行」と「関数定義の実行」は一般的なイディオムではありません。ほとんどの人はそれを単に「関数の定義」と呼ぶだろうと思います。OK、そのフレーズは参照するように解釈されるかもしれません

  1. 関数の特性とインターフェース(パラメーターとその他の入力、処理、および出力)を概念的に指定します(これは、個人または人々のグループによって実行されるアクティビティです)。
  2. 関数の実装を選択する。つまり、関数本体で使用するコマンド。これは、おそらく紙、ホワイトボード、および/または黒板を使用して、個人または人々のグループによって実行されるアクティビティです。
  3. 関数の実装をテキストエディタに入力するか、インタラクティブシェルに直接入力します(これはもちろん、人、または場合によっては人々のグループ、あるいは非常にインテリジェントで器用な猫、犬、猿によって実行されるアクティビティあります) )

上記との混同を恐れる場合は、「関数定義の読み取り」や「関数の定義の処理」などのフレーズを使用した方がよい場合があります。

「関数定義はコマンドです」とあなたは言います。そのような主張が何を意味するのかは明らかではありません—それは意味論の問題です—しかし、意味論レベルでは、それは議論の余地があります。  Bashマニュアル(シェルコマンド)のセクション3.2には、単純コマンド、パイプライン、リスト、複合コマンド、コプロセス、およびGNUParallelの6種類のシェルコマンドがリストされています。関数定義は、これらのカテゴリのいずれにもうまく適合しません。
</ rant>

あなたの質問に行き、7つのステップ/操作を見て、

  1. 入力の読み取りは、他の何か発生する前に明らかに発生する必要があります。繰り返しになりますが、これはセマンティクスの問題です。ファイルまたは他のストリームテキストソースからの入力の読み取りは「関数定義の読み取り」の一部である、または「関数の定義の処理」の前提条件/前置きであると言えます。
  2. 入力を単語と演算子に分割することは、明らかに「関数の定義の処理」の一部です。
    • もちろん、入力をトークンに分割することは、トークンを解析するための前提条件/前置きです(以下のステップ3)。
    • マニュアルには「エイリアス展開はこのステップで実行されます」と書かれており、関数定義を読み取るとエイリアス展開が発生することがわかっていることが質問に示されています。
  3. トークンの解析。これは、シェルが単純なコマンドではなく関数定義を調べていること認識するために、少なくとも「関数の定義の処理」フェーズ中に開始する必要があります。それを超えて、この簡単な実験を行うことができます。シェルに次のいずれかを入力します。

    myfunc1() {                     myfunc2() {
        <               or              ;
    }                               }
    

    を入力する前に、「構文エラー」で失敗します}>そして&同じ効果生み出します。)したがって、明らかにこのステップは関数の定義の処理の一部です。


  1. さまざまなシェル拡張の実行は、関数の呼び出しの一部です。
    • 関数定義が読み取られたときにパラメーター展開発生しないことを知っていることを質問で示します
    • 関数定義が読み取られたときにパス名/ファイル名の展開が行われないことを示すことも同様に簡単です。あなたの例では、echo $var(そうあるべきですがecho "$var"、それは別の問題です)をに変更しecho *ます。
      • 関数定義を見ると、それがまだ表示echo *されており、展開されていないことがわかります
      • ディレクトリの変更(cd)および/またはファイルの作成および/またはファイルの削除および/またはファイルの名前の変更を行ってから、関数を呼び出し(実行)します。現在のディレクトリにあるファイル1の現在のリストを出力し、関数を定義したディレクトリの内容を反映していないことがわかります。
  2. リダイレクトの実行は、関数の呼び出しの一部です。これも確認するのは簡単です。あなたの例では、に変更echo $varecho hello > myfileます。
    • 関数の定義を見ると、まだと書かれていることがわかります > myfile
    • ディレクトリを確認すると、myfileまだ作成されていないことがわかります
  3. コマンドの実行—本当に質問する必要がありますか?
  4. コマンドが完了するのを待つことは、コマンドが実行されるまで(ステップ6)発生しない可能性があるため、これは明らかに関数を呼び出すときにのみ実行されます。

言い換えれば、@ ilkkachuが言っこととまったく同じです。

私が考えることができる1つの例外的な特殊なケースは、関数にevalステートメントが含まれている場合、関数の実行時にステップ2と3(字句解析と構文解析)が(再び)発生することです。しかし、それはあなたの質問が実際に求めている範囲外だと思います。 。
____________
1隠し(ドット)ファイルを除くshopt -s dotglob

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ