私はBashでUbuntu 16.04を使用しており、10の機能を含むファイルがあります。各機能は本質的に異なるタスクを実行します。各関数の終わりに次のように呼び出します。
x() {
echo
}
x
この呼び出しはファイルにさらに10行を追加しますが、審美的な理由でファイルに保存したいと思います。とにかく、ファイルのすべての機能を(すでにソートされた順序で)実行するからです。
もちろん、ソーシング(現在のセッションで実行)やバッシング(サブセッションで実行)だけでは不十分です(時々人々はsource
/bash
すべての機能を実行しない)。
この小さな審美的な問題に対する私の好ましい解決策は、ファイルのソース/攻撃の後にコマンドラインから直接すべての機能を呼び出すことです。
バッシュで可能ですか?
答え1
ファイルの行数にのみ興味がある場合は、次のことができます。
my_func () {
echo "Hello, world"
} && my_func
答え2
あなたはそれを使用することができます:
source <(declare -f | grep -o '^[[:alnum:]]\+')
これは範囲です(declare -f
grep -o '^[[:alnum:]]\+'
)、次に左マージン()内の唯一の英数字文字列である名前のみをフィルタリングし、最後に、次のように関数名の1行に1つずつの結果出力を取得します。プロセスの交換これにより、現在のシェルからすべて呼び出されます。
上記はgrep
使用するGNUまたはBSDに適用されますが、必要に応じて適切なコマンドまたは-o
コマンドに切り替えることができます。sed
awk
ここの関数には特別な順序はありません(Bashのハッシュテーブルの順序は本質的にランダムだと思います)。順序を維持する必要がある場合は、適切に名前を付けてsort
中間に追加してください。
source <(declare -f | grep -o '^[[:alnum:]]\+'|sort)
関数自体を独立して呼び出す場合、この命名構造は望ましくない可能性があります。簡単な解決策は見えません。
これは単一のファイル内で機能します。すでに関数が定義されているシェルにファイルをインポートする場合は、すでに存在する関数を覚えてスキップする必要があります。
funcs=($(declare -f | grep -o '^[[:alnum:]]\+'|sort))
source file
source <(declare -f | grep -o '^[[:alnum:]]\+' | sort - <(printf '%s\n' "${funcs[@]}" | uniq -u)
これを行う方法はいくつかありますが、すべて非常に厄介です。既存の関数をオーバーライドしても失敗します。別のアプローチは、ファイル自体からすべての関数定義行を取得することですgrep
。作成方法を設定しても機能します。
ファイルの内容を制御する場合は、ファイルの下部にある1行の配列定義に呼び出す順序で関数名を一覧表示する方が良いかもしれません。その後、ソースシェルでこれを繰り返して必要な操作を実行できます。
このアプローチはより明確で脆弱ではありません。ただし、両方の位置が同期しない可能性があります。
答え3
本当に1行が必要な場合は、ファイルがあるとし、これを思い出しましたscripts/1.sh
。
shopt -s extdebug; source scripts/1.sh; source="$_"; while IFS= read -r func; do declare_output="$(declare -F "${func##* }")"; [[ ${declare_output##* } == $source ]] && "${func##* }"; done < <(declare -F)
declare
デフォルトでは、これは環境のどの機能がソースファイルから来ているかを確認して実行するために使用されます。scripts/1.sh
echoGoodbye
とcruel
の 3 つの機能があり、world.
このコマンドの出力は次のとおりです。
Goodbye,
cruel
world.
declare
出力順序が関数がソーシングされた順序で保証されるかどうかわからないので、関数名を適切に指定してくださいsort
。
答え4
いくつかの理由で明示的な通話を維持することをお勧めします。呼び出しリストから特定の機能を一時的に削除し、順序を変更し、編集するときに以前のバージョンの機能を維持し、他の機能のみを呼び出すユーティリティ機能を使用できます(「デフォルト」レベルでは呼び出されません)。最後は、プログラムの正しい設定に特に重要なようです。
しかし、本当にしたい場合はできます。少なくとも自動的に実行できる機能の一種のインジケータを追加することをお勧めします。部分的に@casのコメントに基づいて、上記の行に示されている# AUTORUN
すべての機能が実行されます。
#!/bin/bash
foo() { echo foo; }
# AUTORUN
bar() { echo bar; }
while IFS= read -r f; do
$f
done < <(sed -nE '/^# *AUTORUN/!d; n; s/^([a-zA-Z0-9_]+) *\(\).*/\1/p' "${BASH_SOURCE[0]}")
現在の形式のGNU sedが必要な場合があります。