BashでProject Euler(6) ラムダ

前回はパイプを使ったのですが、結局ラムダが使えないので中途半端なんですよね。takewhileやfilterを汎用の関数にできないのです。
しかし、evalを使うとラムダっぽいことができます。

a=1
b=c
eval $b=\$a
echo $c     # 1

evalは、c=$aという文字列をコマンド化しています。右辺の$はエスケープしないとここで$aが変数展開されてしまいます。
これと同様に、ラムダを文字列として変数に代入してevalでコマンド化します。

lambda="test \$x -gt 1"
x=2
if echo $lambda; then
echo $x
fi

test $x -gt 1が評価されて、0が返って、echo $xが実行されます。
これでtakewhileが書けます。

#!/bin/sh
# takewhile.sh

lambda=$1
shift
while [ $# -gt 0 ]; do
    lambda="$lambda $1"
    shift
done

while read x
do
    if eval $lambda; then
        echo $x
    else
        exit
    fi
done

前段は、引数がwhite spaceで区切られて渡されてくるので、それを連結しています。
filterも同様に書けます。

#!/bin/sh
# filter.sh

lambda=$1
shift
while [ $# -gt 0 ]; do
    lambda="$lambda $1"
    shift
done

while read x
do
    if eval $lambda; then
        echo $x
    fi
done

これらをパイプでつないで、

#!/bin/sh

fibs() {
    local m=1
    local n=1
    while :; do
        echo $n
        local tmp=$n
        n=$((n+m))
        m=$tmp
    done
}

fibs | ./takewhile.sh test \$x -le $1 | ./filter.sh test \$\(\(\$x%2\)\) -eq 0 | ./sum.sh

しかし、ここまでやる必要があるのでしょうか。速度も不安です。