shell脚本中的匿名函数

jk9hmnmh  于 2022-11-16  发布在  Shell
关注(0)|答案(7)|浏览(261)

有没有可能创建类似于匿名函数的东西,它的值可以赋给数组元素,然后再调用?我似乎找不到一种方法在bash脚本中做到这一点,但也许有一个变通办法。

vcirk6k6

vcirk6k61#

简短回答:不,不,不
道长回答:不,不,不,不。
完整答案:bash中的函数不是一级对象,因此bash中不可能有匿名函数。

gmol1639

gmol16392#

这是可能的;我写了一个库来完成这个任务,尽管这是一个非常奇怪的项目。源代码可以在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该文件,然后返回其名称。这会导致分散的文件累积,这就是为什么库还实现了异步标记/清除垃圾收集器。

euoag5mw

euoag5mw3#

常用的方法是有条件地分配函数定义:

#!/bin/sh

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

foo
7y4bm7vi

7y4bm7vi4#

如果你真的需要数组来存储函数,你可以定义命名函数,只存储它们的名字,然后调用${array[n]},或者,你可以将它们命名为func1 .. funcN,然后调用func$n

gpnt7bae

gpnt7bae5#

那么bash是图灵机完成,所以这是完全可能的;)
但除此之外,它并不真正值得考虑。
您可以使用沿着以下代码来模拟这种行为:

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

但是为什么呢?

6xfqseft

6xfqseft6#

我遇到这个问题是因为我想知道如何做类似于

[1,2,3,4,5].map(x => x*2).filter(x => x < 7);

即,能够以灵活的方式操纵流水线中的先前结果。

个xargs

我听说过一种在命令行上处理这个问题的好方法,那就是使用xargs命令。

$ printf "one two\nthree\tfour" | xargs echo "args> "
# => args>  one two three four
$ printf "one two three four" | xargs echo "args> "
# => args>  one two three four

默认情况下,它会将标准输入中的任何空格拆分为单独的参数,然后将这些参数提供给命令(下面的示例会更清楚)。
我刚刚学习了**from this extremely helpful gist Brainiarc7 wrote**xargs是如何变得非常灵活和有用的。一定要阅读/浏览它,它真的很好,有更多的解释。我在下面提供了一些例子和我从中收集到的东西,希望它能有所帮助。

1、-n:将参数拆分为n大小的块

# Chunk args into groups of two
$ printf "one two\nthree\tfour" | xargs -n 2 echo "args> "
# =>
# args>  one two
# args>  three four

使用-n 1可能非常有用

2、-I:使用占位符将参数插入命令

对于javascript类比,({arg}) => {body}类似于xargs -I {arg} [other options] {body}

# Split args into groups of two, then interpolate them in the
# command at the `%` placeholder
printf 'one two three four' | xargs -n 2 -I % echo "Chunk of args> " % " <in the middle of a command"
# =>
# Chunk of args>  one two  <in the middle of a command
# Chunk of args>  three four  <in the middle of a command

你给予-I一个字符串作为占位符,占位符可以是你喜欢的任何文本(例如my_unique_placeholder),但是%是常规的。

3、-0:按空字符对参数进行分块(UTF+0000)

这并不方便,但是你可以通过tr用它来按任意字符进行拆分。

# Split arg chunks by tab character:
$ printf 'one two\tthree\tfour' | tr '\t' "\0" | xargs -0 -n 1 echo "args> "
# =>
# args>  one two
# args>  three
# args>  four

4、-L:将n行上的参数拆分为块

# Take all args on every 2 lines as a chunk
$ printf 'one two\nthree\nfour' | xargs -L 2 echo "args> "
# =>
# args>  one two three
# args>  four

https://gist.github.com/Brainiarc7/133fd582e124981c08cbafca98455ee9https://shapeshed.com/unix-xargs/

5uzkadbs

5uzkadbs7#

PATH中创建fn文件

#!/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"

然后,您可以执行以下操作:

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

相关问题