Is it possible to create something analogous to an anonymous function whose value can be assigned to an array element and later called? I can't seem to find a way to do this in a bash script but perhaps there's a workaround.
问题:
回答1:
Short answer: No.
Long answer: Nooooooooooooo.
Complete answer: Functions in bash are not first-class objects, therefore there can be no such thing as an anonymous function in bash.
回答2:
If you really need array to store the functions, you can define named functions and store just their names. You can then call the function as ${array[n]}
. Or, you can name them func1
.. funcN
and then just call func$n
.
回答3:
It is possible; I wrote a library to do exactly this, though it's a very strange project. The source code is available at http://github.com/spencertipping/bash-lambda. Using this library:
$ 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
$
The trick is to have the fn
function create a file containing the body of the function, chmod +x
that file, then return its name. This causes stray files to accumulate, which is why the library also implements an asynchronous mark/sweep garbage collector.
回答4:
The common technique is to assign function definitions conditionally:
#!/bin/sh case $1 in a) foo() { echo case a; };; b) foo() { echo case b; };; *) foo() { echo default; } ;; esac foo
回答5:
Create the fn file in your 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"
You can then do :
foo=$(fn 'echo $1')
${foo} "bar"
回答6:
well bash is turing complete, soo thats perfectly possible ;)
but aside from this its not really worth the consideration.
you could simulate such behaviour though with something along this line:
echo myval ; ( foocmd "$_" && barcmd "$_" )
but why?!?