この目的のために、Bash関数を他の関数(ネストしたものなど)と一緒に宣言/エクスポートすることは可能ですか?

この目的のために、Bash関数を他の関数(ネストしたものなど)と一緒に宣言/エクスポートすることは可能ですか?

たとえば、多少扱いにくいスクリプトでIDEの非常に便利なツリー/概要機能の一部を活用するには、アイテムを入れ子にして折りたたみ可能なツリーにする必要があります。

スクリプト概要ビューの縮小関数

私が理解したのは(私はまだ初心者です)、関数は同じシェルで実行されます。つまり、サブシェルではありません。したがって、これを念頭に置いて大きな関数グループをグループ化して前に置くことができると思いましたset -a。たとえば、別の関数でラップされています。

functiongroup() {        # ← moved from this level ─╮
  set -a                 #                         ╭╯
  func1() { …;}          #   ← grouped functions ──┤
  func2() { …;}          #   ← grouped functions ──╯
  …                      #
}                        #
…                        #
functiongroup            # ← invoke functions function

...または正しく宣言するだけですdeclare

これで問題が発生しますか?

そうでないと仮定すると、彼らはそうです。新しい親関数- スクリプトの特定の場所を攻撃することがわかるように呼び出す必要がありますか?つまり、次のようになります。Bashは親関数を実行する前にネストされた関数を処理(知っています)しますか?

コードが次のようになるとしましょう。

  1 │ #!/usr/bin/env bash
  2 │ # FUNCTIONS & VARS
  3 │ functiongroup() {                # ← moved from this level ─╮
  4 │   set -a                         #                         ╭╯
  5 │   func1() { …;}                  #   ← grouped functions ──┤
  6 │   func2() { …;}                  #   ← grouped functions ──╯
  7 │   …                              #
  8 │ }                                #
  9 │ # PROGRAM                        #
 10 │                                  # ← moved to line 12
 11 │ echo -n "something $(func2)"     # ← func2 call
 12 │ functiongroup                    # ← accidentally moved a line too late
 13 │ if func1; then                   # ← func1 call                  
 14 │   do                             #         
 15 │     …                            #         
 16 │   done                           #           
 17 │ else                             #       
 18 │   echo "MELTDOWN!"               #           
 19 │   exit 1                         #           
 20 │ fi                               #           
 21 │ exit 0                           #           

上でfunc1実行されますかfunc2、それとも単に実行されますかfunc1? (そうであれば)

私の参照はGNUですバッシュマニュアル時にはあまりにも細かいことがあるので、これと比較しました。カンニング紙StackExchangeのアイデアをたくさん見つけましたが、完全に理解していないとコードを使用しないため、必要なだけ早く学習することはできません。確かに線形ではありません。 :(

私はこれが簡単で、最終的なスクリプトが何をしているのかをいつでも知ることができるので、これが好きです。しかし、それを構成する適切でより良い方法がある場合は、お知らせください。

ありがとうございます。


*:後で必要な知識レベルに達したときに確認できるように、コードスニペットをメモに保存しますが、覚えている限り。 Bash、PHP、Python、JavaScript、PowerShell、さらにはHTMLまで...検閲されていないコードのバックログがあります。

答え1

Bashは親関数を実行する前にネストされた関数を処理(知っています)しますか?

いいえ。

一度試してみましょう:

$ funcgroup() {
    f1() { echo this is f1; }
    f2() { echo this is f2; }
}

$ f2
f2: command not found

$ funcgroup

$ f2
this is f2

スクリプトを使用するのが難しい場合は、関数をライブラリに分割してください。

$ bash

$ cat funcs.bash
f1() { echo this is f1; }
f2() { echo this is f2; }

$ f2
f2: command not found

$ . funcs.bash

$ f2
this is f2

.(別名)コマンドは、source現在のディレクトリとPATHでファイルを検索します。

答え2

最初の答えからわかるように、通常、プログラムを別々のモジュールにソートすることをお勧めします。特に、あまりにも多くのスペースを占める肥大したソフトウェアはさらにそうです。

しかし、問題は、スクリプトを呼び出す方法に注意する必要があることです。パスが変更され、初期スクリプトが最終的にライブラリを見つけることができないため、ライブラリをインポートする初期スクリプトを呼び出す場所とは異なります。

私は通常、この問題を回避するために次の機能を使用します。

function whereAmI { printf "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"; }

これは、このプロセスを実行するスクリプトがどこにあるかを示します。

したがって、ライブラリが初期スクリプトに関連するどこかにある場合は、常にライブラリを探します。たとえば、対応する相対パスにlib/結果を追加する場合です。whereAmI

それにもかかわらず、言語の制限のためにBashコードをうまく整理することが重要です。そうでなければ、今から1年後に見ると、すべてが言葉になりません。

関連情報