bash-fun

Functional programming in bash
授权协议 MIT License
开发语言 SHELL
所属分类 应用工具、 终端/远程登录
软件类型 开源软件
地区 不详
投 递 者 锺离浩慨
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Introduction

Introduction to fun.sh library

Quick start

#!/bin/bash
. <(test -e fun.sh || curl -Ls https://raw.githubusercontent.com/ssledz/bash-fun/master/src/fun.sh > fun.sh; cat fun.sh)

seq 1 4 | sum

Functions overview

append buff call catch curry div
drop dropw factorial filter foldl foldr
isint isempty isfile isnonzerofile isreadable iswritable
isdir join lambda last lhead list
ltail lzip map maybe maybemap maybevalue
mod mul not ntup ntupl ntupr
ntupx peek plus prepend product ret
res revers revers_str scanl splitc strip
stripl stripr sub sum take try
tup tupl tupr tupx unlist λ
with_trampoline

list/unlist

$ list 1 2 3
1
2
3

$ list 1 2 3 4 5 | unlist
1 2 3 4 5

take/drop/ltail/lhead/last

$ list 1 2 3 4 | drop 2
3
4

$ list 1 2 3 4 5 | lhead
1

$ list 1 2 3 4 | ltail
2
3
4

$ list 1 2 3 4 5 | last
5

$ list 1 2 3 4 5 | take 2
1
2

join

$ list 1 2 3 4 5 | join ,
1,2,3,4,5

$ list 1 2 3 4 5 | join , [ ]
[1,2,3,4,5]

map

$ seq 1 5 | map λ a . 'echo $((a + 5))'
6
7
8
9
10

$ list a b s d e | map λ a . 'echo $a$(echo $a | tr a-z A-Z)'
aA
bB
sS
dD
eE

$ list 1 2 3 | map echo
1
2
3

$ list 1 2 3 | map 'echo $ is a number'
1 is a number
2 is a number
3 is a number

$ list 1 2 3 4 | map 'echo \($,$\) is a point'
(1,1) is a point
(2,2) is a point
(3,3) is a point
(4,4) is a point

flat map

$ seq 2 3 | map λ a . 'seq 1 $a' | join , [ ]
[1,2,1,2,3]

$ list a b c | map λ a . 'echo $a; echo $a | tr a-z A-z' | join , [ ]
[a,A,b,B,c,C]

filter

$ seq 1 10 | filter λ a . '[[ $(mod $a 2) -eq 0 ]] && ret true || ret false'
2
4
6
8
10

foldl/foldr

$ list a b c d | foldl λ acc el . 'echo -n $acc-$el'
a-b-c-d

$ list '' a b c d | foldr λ acc el .\
    'if [[ ! -z $acc ]]; then echo -n $acc-$el; else echo -n $el; fi'
d-c-b-a
$ seq 1 4 | foldl λ acc el . 'echo $(($acc + $el))'
10
$ seq 1 4 | foldl λ acc el . 'echo $(mul $(($acc + 1)) $el)'
64 # 1 + (1 + 1) * 2 + (4 + 1) * 3 + (15 + 1) * 4 = 64

$ seq 1 4 | foldr λ acc el . 'echo $(mul $(($acc + 1)) $el)'
56 # 1 + (1 + 1) * 4 + (8 + 1) * 3 + (27 + 1) * 2 = 56

tup/tupx/tupl/tupr

$ tup a 1
(a,1)

$ tup 'foo bar' 1 'one' 2
(foo bar,1,one,2)

$ tup , 1 3
(u002c,1,3)
$ tupl $(tup a 1)
a

$ tupr $(tup a 1)
1

$ tup , 1 3 | tupl
,

$ tup 'foo bar' 1 'one' 2 | tupl
foo bar

$ tup 'foo bar' 1 'one' 2 | tupr
2
$ tup 'foo bar' 1 'one' 2 | tupx 2
1

$ tup 'foo bar' 1 'one' 2 | tupx 1,3
foo bar
one

$ tup 'foo bar' 1 'one' 2 | tupx 2-4
1
one
2

ntup/ntupx/ntupl/ntupr

$ ntup tuples that $(ntup safely nest)
(dHVwbGVzCg==,dGhhdAo=,KGMyRm1aV3g1Q2c9PSxibVZ6ZEFvPSkK)

echo '(dHVwbGVzCg==,dGhhdAo=,KGMyRm1aV3g1Q2c9PSxibVZ6ZEFvPSkK)' | ntupx 3 | ntupr
nest

$ ntup 'foo,bar' 1 one 1
(Zm9vLGJhcgo=,MQo=,b25lCg==,MQo=)

$ echo '(Zm9vLGJhcgo=,MQo=,b25lCg==,MQo=)' | ntupx 1
foo,bar
$ ntupl $(ntup 'foo bar' 1 one 2)
foo bar

$ ntupr $(ntup 'foo bar' 1 one 2)
2

buff

$ seq 1 10 | buff λ a b . 'echo $(($a + $b))'
3
7
11
15
19

$ seq 1 10 | buff λ a b c d e . 'echo $(($a + $b + $c + $d + $e))'
15
40

lzip

$ list a b c d e f | lzip $(seq 1 10)
(a,1)
(b,2)
(c,3)
(d,4)
(e,5)
(f,6)
$ list a b c d e f | lzip $(seq 1 10) | last | tupr
6

curry

add2() {
    echo $(($1 + $2))
}
$ curry inc add2 1
$ inc 2
3

$ seq 1 3 | map λ a . 'inc $a'
2
3
4

peek

$ list 1 2 3 \
    | peek lambda a . echo 'dbg a : $a' \
    | map lambda a . 'mul $a 2' \
    | peek lambda a . echo 'dbg b : $a' \
    | sum

dbg a : 1
dbg a : 2
dbg a : 3
dbg b : 2
dbg b : 4
dbg b : 6
12
$ a=$(seq 1 4 | peek lambda a . echo 'dbg: $a' | sum)

dbg: 1
dbg: 2
dbg: 3
dbg: 4

$ echo $a

10

maybe/maybemap/maybevalue

$ list Hello | maybe
(Just,Hello)

$ list "   " | maybe
(Nothing)

$ list Hello | maybe | maybemap λ a . 'tr oH Oh <<<$a'
(Just,hellO)

$ list "   " | maybe | maybemap λ a . 'tr oH Oh <<<$a'
(Nothing)

$ echo bash-fun rocks | maybe | maybevalue DEFAULT
bash-fun rocks

$ echo | maybe | maybevalue DEFAULT
DEFAULT

not/isint/isempty

$ isint 42
true

$ list blah | isint
false

$ not true
false

$ not isint 777
false

$ list 1 2 "" c d 6 | filter λ a . 'isint $a'
1
2
6

$ list 1 2 "" c d 6 | filter λ a . 'not isempty $a'
1
2
c
d
6

isfile/isnonzerofile/isreadable/iswritable/isdir

$ touch /tmp/foo

$ isfile /tmp/foo
true

$ not iswritable /
true

$ files="/etc/passwd /etc/sudoers /tmp /tmp/foo /no_such_file"

$ list $files | filter λ a . 'isfile $a'
/etc/passwd
/etc/sudoers
/tmp/foo

$ list $files | filter λ a . 'isdir $a'
/tmp

$ list $files | filter λ a . 'isreadable $a'
/etc/passwd
/tmp
/tmp/foo

$ list $files | filter λ a . 'iswritable $a'
/tmp
/tmp/foo

$ list $files | filter λ a . 'isnonzerofile $a'
/etc/passwd
/etc/sudoers
/tmp

$ list $files | filter λ a . 'not isfile $a'
/tmp
/no_such_file

try/catch

$ echo 'expr 2 / 0' | try λ _ . 'echo 0'
0

$ echo 'expr 2 / 0' | try λ status . 'echo $status'
2

$ echo 'expr 2 / 2' | try λ _ . 'echo 0'
1
try λ  _ . 'echo some errors during pull; exit 1' < <(echo git pull)
$ echo 'expr 2 / 0' \
    | LANG=en catch λ cmd status val . 'echo cmd=$cmd,status=$status,val=$val'
cmd=expr 2 / 0,status=2,val=(expr:,division,by,zero)
$ echo 'expr 2 / 2' | catch λ _ _ val . 'tupl $val'
1

scanl

$ seq 1 5 | scanl lambda acc el . 'echo $(($acc + $el))'
1
3
6
10
15
$ seq 1 5 | scanl lambda a b . 'echo $(($a + $b))' | last
15

with_trampoline/res/call

factorial() {
    fact_iter() {
        local product=$1
        local counter=$2
        local max_count=$3
        if [[ $counter -gt $max_count ]]; then
            res $product
        else
            call fact_iter $(echo $counter\*$product | bc) $(($counter + 1)) $max_count
        fi
    }

    with_trampoline fact_iter 1 1 $1
}
$ time factorial 30 | fold -w 70
265252859812191058636308480000000

real    0m1.854s
user    0m0.072s
sys     0m0.368s
time factorial 60 | fold -w 70
8320987112741390144276341183223364380754172606361245952449277696409600
000000000000

real    0m3.635s
user    0m0.148s
sys     0m0.692s
$ time factorial 90 | fold -w 70
1485715964481761497309522733620825737885569961284688766942216863704985
393094065876545992131370884059645617234469978112000000000000000000000

real    0m4.371s
user    0m0.108s
sys     0m0.436s

Examples

processNames() {

  uppercase() {
     local str=$1
     echo $(tr 'a-z' 'A-Z' <<< ${str:0:1})${str:1}
  }

  list $@ \
    | filter λ name . '[[ ${#name} -gt 1 ]] && ret true || ret false' \
    | map λ name . 'uppercase $name' \
    | foldl λ acc el . 'echo $acc,$el'

}

processNames adam monika s slawek d daniel Bartek j k
Adam,Monika,Slawek,Daniel,Bartek

Running tests

cd test
./test_runner

Contribution guidelines

Feel free to ask questions in chat, open issues, or contribute by creating pull requests.

In order to create a pull request

  • checkout master branch
  • introduce your changes & bump version
  • submit pull request

Resources

  • 日前Linux官方内置Bash中新发现一个非常严重安全为了避免您Linux服务器受影响,建议您尽快完成漏洞修补,修复方法如下: 【已确认被成功利用的软件及系统】 所有安装GNUbash版本小于或者等于4.3的Linux操作系统。 【漏洞描述】 该漏洞源于你调用的bash shell之前创建的特殊的环境变量,这些变量可以包含代码,同时会被bash执行。 【漏洞检测方法】 可以使用如下命令来检查系统存

  • 日前Linux官方内置Bash中新发现一个非常严重安全为了避免您Linux服务器受影响,建议您尽快完成漏洞修补,修复方法如下: 【已确认被成功利用的软件及系统】 所有安装GNUbash版本小于或者等于4.3的Linux操作系统。 【漏洞描述】 该漏洞源于你调用的bash shell之前创建的特殊的环境变量,这些变量可以包含代码,同时会被bash执行。 【漏洞检测方法】 可以使用如下命令来检查系统存

  • bash 重定向 Bash重定向:基础知识 (Bash Redirection: The Basics) A bash script is commonly a set of commands. There are three standard file descriptors of any command: bash脚本通常是一组命令。 任何命令都有三个标准文件描述符: 0 → stdin 0→

  • 米扑科技,这两天需要在Ubuntu中配置开机启动的命令,有很多方式 在rc.local中配置是比较简单方便的一种,所以打算使用rc.local的方式进行配置。 简介 /etc/rc.local 实际上是一个文件软链接,指向真实的文件是 /etc/rc.d/rc.local # ll /etc/rc.local lrwxrwxrwx. 1 root root 13 8月 14 00:20 /etc/

  • k3s install #centos8x64 #using bash ##1. download k3s mkdir /home/z/k3s_home/ ; cd /home/z/k3s_home/ wget https://github.91chi.fun//https://github.com//k3s-io/k3s/releases/download/v1.24.4%2Bk3s1/k

 相关资料
  • 好了,现在我们换了一个遥控器,感觉顺手多了。现在来操练一下,下载一首 mp3: 我们使用 wget 这个程序,它非常可靠,完全值得您信赖。 首先找到一个可以下载的地址,复制链接,在终端窗口内点击鼠标中键,把它粘贴进去。 现在终端中大概是这种情形: http://linuxtoy.org/xxx.mp3 按下 Ctrl+a 组合键,我们发现光标移动到了行首。输入 wget 和 空格 wget ht

  • 语法 基本语法 名称 语法 描述 示例 interpreter #!/bin/bash Bash shell 脚本的第一行以 #! 开头,通常也称为 sharp-bang 或缩写版本 sha-bang。后面的路径名称是命令解释器,也就是应该用于执行脚本的程序。 echo echo "arbitrary text" echo "arbitrary text" >&2 文本定向到标准输出 (STDOU

  • bash 是一个为GNU项目编写的Unix shell。它的名字是一系列缩写:Bourne-Again SHell — 这是关于Bourne shell(sh)的一个双关语(Bourne again / born again)。Bourne shell是一个早期的重要shell,由Stephen Bourne在1978年前后编写,并同Version 7 Unix一起发布。bash则在1987年由B

  • Bash++ 是一个将 bash 提升到一个新水平的框架,为 bash 引入了新功能。它的设计是为了让人们能够建立更复杂的应用程序,创造更好的产品。 请注意,这个项目是为有 bash 经验的人准备的(不多,只是简单的理解和事情通常如何运作)。 运行示例 (确保你已经安装bash++) cd 进入示例目录。 对你想运行的脚本进行chmod。 chmod +x [SCRIPT.sh] 运行该脚本 ./[SCRIPT].sh

  • Bash-it 是一款针对bash使用进行优化的软件,提供了终端显示的主题优化、命令补全、命令别名、插件、版本控制目录状态实时显示等实用功能,能让bash更好用!正如软件readme说的那样,本款软件是模仿 http://www.oschina.net/p/oh-my-zsh 的,只不过是使用在bash环境中。 安装本软件需要有bash(这个大多数类Unix系统都具备)、git(如果下载zip包也

  • Bash-Snippets 这个项目完全是为重度终端用户而生的,里面包含了大量的 Bash 脚本,而且无需任何依赖。 示例: Crypt 封装了 openssl,可用于快速加密和解密文件 crypt -e [original file] [encrypted file] # encrypts filescrypt -d [encrypted file] [output file] # decryp

  • 黑客对linux发展贡献是非常多的。Bash命令自动完成功能只不过是收集各种黑客指定参数是如何通过Readline使用内置完成来完成的。该功能在其他linux分支是启用的,如ubuntu、debian等等。然而,基于RHCE分支发布的linux版本却没有安装和启用,如CentOS。 如果你使用过ubuntu系统,bash命令自动补齐会觉得非常方便高效。再使用RHCE或CentOS的话,你肯定会吐槽

  • bash-handbook This document is written for those who want to learn Bash without diving in too deeply. Tip: Try learnyoubash — an interactive workshopper based on this handbook! Node Packaged Manuscrip