2011-12-08 42 views
21

配列要素に値を割り当てて後で呼び出すことができる無名関数に類似したものを作成することは可能ですか?私はbashスクリプトでこれを行う方法を見つけることができないようですが、おそらく回避策があります。シェルスクリプト内の匿名関数

答えて

47

短い回答:いいえ

長い答え:Nooooooooooooo。

完全な答え:bashの関数はファーストクラスのオブジェクトではないため、bashには無名関数のようなものはありません。

+5

回避策として、名前を持つ関数を定義し、名前だけを配列に格納します。関数を呼び出すときに配列要素を 'eval'するだけです。 – choroba

+1

@chorobおそらく答えとして投稿するべきです。 Ignacioの説明どおりに直接的には可能ではありませんが、あなたの回避策は良い考えです。 – Matty

+0

CVE-2014-6271 [link](https://www.reddit.com/r/netsec/comments/2hbxtc/cve20146271_remote_code_execution_through_through_bash/ckrhvtl)のbashバグは、シェルスクリプトに匿名機能が存在することを確認していますか? – Lizz

5

一般的な手法は、条件付きで関数定義を割り当てることです:あなたが本当に機能を格納する配列が必要な場合は、名前の関数を定義し、その名前だけを保存することができます

 
#!/bin/sh 

case $1 in 
a) foo() { echo case a; };; 
b) foo() { echo case b; };; 
*) foo() { echo default; } ;; 
esac 

foo 
8

。その後、関数を${array[n]}と呼び出すことができます。または、func1の名前を付けてfuncNとし、func$nを呼び出してください。

7

可能です。私は非常に奇妙なプロジェクトですが、これを正確に行うライブラリを作成しました。ソースコードはhttp://github.com/spencertipping/bash-lambdaにあります。このライブラリを使用する:

$ my_array=() 
$ my_array[0]=$(fn x 'echo $((x + 1))') 
$ my_array[1]=$(fn x 'echo $((x + 2))') 
$ ${my_array[0]} 5 
6 
$ ${my_array[1]} 5 
7 
$ 

トリックはfn関数は、その後、機能、ファイルchmod +xの身体を含むファイルを作成し、その名前を返すことです。これにより、迷子ファイルが蓄積されます。そのため、ライブラリでは非同期マーク/スイープガベージコレクタも実装されています。

+0

匿名関数を実行する前にコマンドの実行が完了するのを待つ方法はありますか? – William

0

ます。次に行うことができますPATH

#!/bin/sh 

printusage() { 
     printf "Create anonymous function, for example\n" 
     printf "fn 'echo "$1 $2"'" 
     exit 1 
} 


[ "$#" = "1" ] || printusage 
fun=$1 
[ "$fun" = "" ] && printusage 
fun_file="$(mktemp /tmp/fun_XXXXXX)" 

echo "#!/bin/sh" > "$fun_file" 
echo "" >> "$fun_file" 
echo "$fun" >> "$fun_file" 
chmod u+x "$fun_file" 

echo "$fun_file" 

にFNファイルを作成します。

foo=$(fn 'echo $1') 
${foo} "bar" 
0

もbashは洙完全に可能厥、チューリング完全である;)

が、これとは別にそれは本当に考慮に値するものではありません。

あなたはこの線に沿って何かをかかわらず、このような行動をシミュレートすることができます:

echo myval ; (foocmd "$_" && barcmd "$_") 

が、なぜ?!?