command
私は関数なら何かを実行するBashの組み込み機能に似たものを探しています。したがって、現在安全でないアプローチがあります。
# Go through arguments in order
for i in $*; do
if [ -z `which $i` ]; then
# Run function
$i && echo -n ' '
fi
done
このifステートメントは正しく機能しません。とにかく、それが関数ではなくコマンドであるかどうかを確認できても、明示的に関数を実行することはできません。これは、誰かが$ PATHに私の関数と同じ名前のプログラムを持っている場合に実行されるため、これはお勧めできません。 PATHをキャンセルしたり他のものに設定したりしても、誰でも$ iを使って明示的にプログラムを実行できるので、これも解決策ではありません。
私のシェルスクリプトを「保護」する方法はありますか?
答え1
を使用すると、bash
次のことができます。
for f do
if declare -F -- "$f" >/dev/null 2>&1; then
: "$f" is a function, do something with it
fi
done
declare -F -- "$f" >/dev/null 2>&1
$f
bash関数の場合、成功コードが返され、何も出力されません。
bash
POSIXモードで実行するときbuiltin enable -n -- "$f"
。
答え2
Bashが提供する正式な方法は、組み込みtype
のas ofを使用することですtype -t
。
function fun() {
: foo bar
}
if [ function = $(type -t fun) ]; then
echo fun is a function.
fi
引数リストの関数名が疑わしい場合は、二重引用符で囲みます。$(type -t "$arg")
答え3
bash
シェルにすでに設定されている可能性がありますが、このような移植可能な操作を実行するには、次のものを使用できます。
eval " for c in $(unalias -a
for c do case ${c#function} in
(*[!_[:alnum:]]*) ;; (?*)
PATH= command -v "$c" >&2 &&
PATH= command -V "$c" &&
printf '\n'"'$c'"'\\\0'
esac 2>/dev/null; done |
tr '\t\n\0' ' \n' |
sed -ne's/.* function .* / /p')"'
;do "$c"; printf %02s
done'
それは段階的に進みます:
- まず、最初にシェル名で不適切にする文字を含むすべてのパラメータを消去します。
- 現在の引数が有効な名前の場合そして有効なシェル組み込みまたは関数は、名前と型を標準出力に出力します。シェルは出力方法を変更できるため、
command -V
出力を1行にすることはできません。したがって、出力の後には、我々が検証した名前とnullバイトが続きます。 tr
すべての改行とタブを空白に変換し、すべてのヌルバイトを改行に変換します。- 、すべての行の最後の空白文字を置き換え、行も文字列と一致する場合は
sed
結果を印刷します。s///
function
。 - すべての
sed
出力は外部ループのイテレータに丸められ、各イテレータは順番に実行され、各for
実行後にprintf
2つのスペースが書き込まれます。