Bash版的join,map和filter
今天看到有人用Bash实现了join,map和filer函数(可惜没有reduce函数),觉得很有趣,所以记录下来
join 函数
join() { { local indelimiter; indelimiter="${1- }" ; local outdelimiter; outdelimiter="${2-.}" ; } local car local cdr local IFS IFS="${indelimiter}" read -t 1 car cdr || return test "${cdr}" || { echo "${car}" ; return ; } echo "${car}${outdelimiter}${cdr}" | ${FUNCNAME} "${indelimiter}" "${outdelimiter}" }
map 函数
map() { { local function_name ; function_name="${1}" ; } local car local cdr local IFS IFS="${indelimiter- }" read -t 1 car cdr || return test "$( declare -f ${function_name} )" || return test "${car}" || { true ; return ; } ${function_name} ${car} echo "${cdr}" | ${FUNCNAME} "${function_name}" }
filter 函数
filter() { { local function_name ; function_name="${1}" ; } local car local cdr local IFS IFS="${indelimiter- }" read -t 1 car cdr || return test "$( declare -f ${function_name} )" || return test "${car}" || { true ; return ; } ${function_name} "${car}" || echo -n "${car} " echo "${cdr}" | ${FUNCNAME} "${function_name}" }
上面定义的三个函数都遵循一个模式:
- 数据通过
read
读入,这样的好处是数据可以是任意长度 - 所有的数据都被
read
分成 car 和 cdr 两部分(一看就是玩lisp的;>) - 在函数内使用
FUNCNAME
引用自身的函数名来实现递归 - 为了避免递归陷入死循环,需要对
car
或cdr
进行检查,提前退出。
参照这个模板的,我们也可以很容易定义出reduce函数
reduce() { { local function_name ; function_name="${1}" ; } local first local second local cdr local IFS IFS="${indelimiter- }" read -t 1 first second cdr || return test "$( declare -f ${function_name} )" || return test -n "${second}" || { echo ${first} ; return ; } first=$(${function_name} ${first} ${second}) echo "${first}${IFS}${cdr}" | ${FUNCNAME} "${function_name}" }
我们来测试一把
source ~/bin/autoload/reduce.sh sum() { expr $1 \+ $2 } echo {1..4} |reduce sum
10