Skip to content

some useful lib function for bash(一些有用的shell函数库)

License

Notifications You must be signed in to change notification settings

malongshuai/shell_libs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Shell(Bash)库函数

这些库函数完全使用bash内置命令和bash自身特性编写,未使用任何外部命令,且除了测试库函数,其他所有库函数都未使用任何影响效率的行为(例如命令替换、进程替换、管道导致的额外进程,等等),因此,效率在shell层次上是有保证的。

这些库函数可以作为一个不错的学习和深入理解bash内置特性的途径。

欢迎issue提出问题。

用法

先下载或克隆:

git clone https://github.com/malongshuai/shell_libs.git
cd shell_libs

执行import_shell_libs.sh

bash import_shell_libs.sh

这将会拷贝所有的库函数文件(除import_shell_libs.sh外)到/etc/profile.d/shell_libs目录,并生成/etc/profile.d/import_shell_libs.sh文件,该文件用于加载拷贝到shell_libs目录下的所有库文件。

重新登录bash(以及以后每次登录bash),将加载这些库函数文件。

exec bash -l

现在可以使用这些库函数。例如使用库函数rand生成指定范围内的随机整数:

rand 100   # 生成0到100(不包括100)之间的随机整数

如果要在脚本中使用这些库函数,则在脚本中加上如下一行手动source加载库文件。

source /etc/profile.d/import_shell_libs.sh

库函数文档

说明:这些库函数中,可以输出结果的库函数,也都可以使用-v Var将结果赋值给shell变量而不输出。

例如:

upcase "hello world"

将输出HELLO WORLD

upcase -v big "hello world"

不会输出,而是将HELLO WORLD赋值给shell变量big。

因此,下面两条命令在效果上是等价的,都将大写后的字符串赋值给变量big,但后者效率更高:

big="$(upcase "hello world")"
upcase -v big "hello world"

数值类库函数

包括如下几个数值类的库函数:

  • is_int:判断给定参数是否是整数
  • rand:生成给定范围的随机整数

is_int

判断给定参数是否是整数。如果给定参数是整数,退出状态码为0,否则退出状态码为1。

# 下面几个命令的退出状态码为0
is_int 3
is_int 2312
is_int 033     # 判断8进制整数
is_int 0x33    # 判断16进制整数
is_int 0b1001  # 判断二进制整数

# 下面几个命令的退出状态码为1
is_int ab
is_int     # 无参数

rand

rand [-v Var] [N]

生成指定范围0-N(不包括N)之间的随机整数。如果省略N,则等价于bash RANDOM变量,生成0-32767范围内的随机整数。

默认输出所生成的随机整数,使用-v Var选项,可将生成的随机整数赋值给shell变量而不是输出。

rand   # 输出0-32767之间的随机整数
rand 10  # 输出0-10之间的随机整数

rand -v r 100 # 生成0-100之间的随机整数并赋值给变量r

数组类库函数

bash的数组可以是数值索引数组,也可以字符串索引的关联数组(即hash结构)。此处所列功能皆为数值索引数组而设计,虽然部分也可以应用于关联数组,但结果不可预测。

包括如下几个数值索引数组类的库函数:

  • new_arr:根据指定格式的字符串构建数组
  • push:向数组尾部追加一个或多个元素
  • pop:移除数组最后一个元素,并输出该元素或将其赋值给指定的变量
  • unshift:向数组头部插入一个或多个元素
  • shift_arr:移除数组第一个元素,并输出该元素或将其赋值给指定的变量
  • extend:扩展数组
  • join:使用指定字符串连接数组各元素
  • slice:获取数组的slice

new_arr

new_arr Arr_Name String

将给定的字符串String转换为数组Arr_Name。支持转换的String格式为(elem1 elem2 elem3...)

建议:String部分使用引号保护。

例如:

$ new_arr arr '(a b c "d e")'
$ # 等价于 arr=(a b c "d e")
$ declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d e")

push

push ARR e1 [e2 e3 ...]

向数组ARR尾部追加一个或多个元素。

例如:

push arr a b 'c d' e  # arr=(a b "c d" e)
push arr aa bb    # arr=(a b "c d" e aa bb)

unshift

unshift Arr e1 [e2 e3 ...]

向数组Arr的头部插入一个或多个元素。如果插入的是多个元素,则一次性插入。

例如:

unshift arr "a"  # arr=(a)
unshift arr "a" "b" "c" # arr=(a b c a)

pop

pop [-v Var] Arr

移除数组Arr最后一个元素,并输出该元素,或者指定-v Var选项将该元素赋值给shell变量Var而不再输出。如果数组Arr为空数组,则什么也不做,并且设置退出状态码为1。

例如:

arr=(a b c d)
pop arr   # 输出d,arr=(a b c)
pop -v l arr # 将c赋值给变量l,arr=(a b)

shift_arr

shift_arr [-v Var] Arr

移除数组Arr第一个元素,并输出该元素,或者指定-v Var选项将该元素赋值给shell变量Var而不再输出。如果数组Arr为空数组,则什么也不做,并且设置退出状态码为1。

说明:因为bash已经内置了一个shift命令,shift命令用于操作位置参数。因此,该函数命名为shift_arr,表示操作数组的shift。

例如:

arr=(a b c d)
shift_arr arr  # 输出a,arr=(b c d)
shift_arr -v l arr # 将b赋值给变量l,arr=(c d)

extend

extend Arr Arr1 Arr2 ...
extend Arr String1 String2 ...

扩展数组。可以将其他数组变量Arr1、Arr2的元素扩展到数组Arr中,也可以将字符串格式的数组(将使用new_arr将字符串转换为数组)扩展到数组Arr。

例如:

arr1=(a b c)
extend arr arr1       
#=> arr=(a b c)

arr2=(aa bb cc)
arr3=(d "e e" f)
extend arr arr2 arr3  
#=> arr=(a b c aa bb cc d "e e" f)

extend arr9 '(a b c)' '(d e)' arr1
#=> arr9=(a b c d e a b c)

join

join [-v Var] Array_Name [Sep]

使用指定的字符串串联数组各元素,如果未指定连接符,则默认使用空格串联。使用-v Var选项可以将串联后的结果赋值给变量,否则将输出串联后的结果。

例如:

arr=(a b c d)
join arr ,      # 输出:a,b,c,d
join arr        # 输出:a b c d
join arr '--'   # 输出:a--b--c--d
join -v joined arr ',' # joined='a,b,c,d'

slice

slice -v Arr_Var Arr
slice -v Arr_Var M..N Arr
slice -v Arr_Var N [Len] Arr

获取数组Arr的切片,将切片元素保存到Arr_Var数组中。注意,数组Arr要求是数值索引的数组,不能是关联数组。

对于语法(1),表示获取Arr的所有字符,即Arr的副本。

对于语法(2),表示获取Arr中指定范围的元素。支持的范围语法包括M..N, ..N, M..。M和N代表索引,它们可以是负数,表示从右向左的索引,-1表示倒数第一个元素,-2表示倒数第二个元素。但要注意,指定的范围是合法的,不允许M代表的索引位置在N代表的索引位置的右边。

对于语法(3),表示从索引位置N处开始,获取Len个元素。N可以为负数,表示从右向左计算负数索引位置。如果省略Len参数,表示获取从N开始的剩余所有元素。Len也可以为负数,此时它不表示长度,而是表示获取的终止索引位置,且从右向左计算负数索引位置。

例如:

local test_arr=(0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h)
local res_arr
slice -v res_arr 7 test_arr       # "(7 8 9 0 a b c d e f g h)"
slice -v res_arr 7 0 test_arr     # "()"
slice -v res_arr 7 2 test_arr     # "(7 8)"
slice -v res_arr 7 -2 test_arr    # "(7 8 9 0 a b c d e f)"
slice -v res_arr -7 test_arr      # "(b c d e f g h)"
slice -v res_arr -7 2 test_arr    # "(b c)"
slice -v res_arr -7 -2 test_arr   # "(b c d e f)"
slice -v res_arr test_arr         # "(0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h)"
slice -v res_arr 1..3 test_arr    # "(1 2 3)"
slice -v res_arr 7.. test_arr     # "(7 8 9 0 a b c d e f g h)"
slice -v res_arr ..7 test_arr     # "(0 1 2 3 4 5 6 7)"
slice -v res_arr 1..-7 test_arr   # "(1 2 3 4 5 6 7 8 9 0 a b)"
slice -v res_arr -7.. test_arr    # "(b c d e f g h)"
slice -v res_arr ..-7 test_arr    # "(0 1 2 3 4 5 6 7 8 9 0 a b)"
slice -v res_arr -10..-7 test_arr # "(9 0 a b)"

字符串类库函数

包括如下几个字符串类的库函数:

  • downcase:将字符串转换为小写
  • upcase:将字符串转换为大写
  • repeat_str:重复字符串指定次数
  • center:将字符串居中
  • trim:根据指定的字符串,修剪字符串中左右两边的字符
  • squash:压缩连续的指定字符
  • split:根据指定分隔符,将字符串划分为数组
  • index:搜索字符串中指定子串第一次出现的索引位置
  • index_all:搜索字符串中指定子串的所有索引位置
  • chars:将字符串每个字符保存到数组
  • str_slice:获取字符串的子串
  • random_str: 生成指定长度的随机数字、随机大小写字母、随机标点或它们的组合

downcase和upcase

downcase [-v Var] Str
upcase [-v Var] Str

将字符串转换为大写、小写。默认将输出转换后的字符串,指定-v Var选项,转换后的字符串将赋值给变量而非输出。

例如:

downcase 'HELLO WORLD' # 输出:"hello world"
upcase -v upstr 'hello world'  # upstr="HELLO WORLD"

repeat_str

repeat_str [-v Var] Str N

重复字符串N次(N为正整数)。指定-v Var可将重复后的字符串赋值给变量,否则将输出重复后的字符串。

例如:

repeat_str - 5        # 输出:"-----"
repeat_str -v s ab 3  # s="ababab"

center

center [-v Var] [-l Len] [-p Padding_str] Str

居中显示字符串。

  • -v Var表示将居中后的字符串赋值给变量,否则将输出居中后的字符串
  • -l Len表示居中后的字符串长度(字符数),如果不指定该选项,则默认总长度为80
  • -p Padding_str表示使用字符串Padding_str填充在左右两边

例如:

center -l 10 "hell"   # '   hell   '
center -l 10 "hello"  # '   hello  '

center -l 15 "hell" 
#=> "      hell     "
center -l 15 -p abc " hell " 
#=> "abcab hell abca"
center -l 15 -p abc " hihello " 
#=> "abc hihello abc"

trim

trim [-l] [-r] [-v Var] [Target] String

修剪String字符串左边和右边的字符。

  • -l选项表示修剪左边
  • -r选项表示修剪右边
  • -v Var表示将修剪后的字符串赋值给变量Var,否则将输出修剪后的字符串
  • Target表示要修剪左右两边的什么字符,未指定Target时,默认将修剪空白字符

当未指定-l-r时,默认同时修剪左右两边,等价于同时指定它们。

例如:

trim '  a b  '       # "a b"
trim -l '  a b  '    # "a b  "
trim -r '  a b  '    # "  a b"
trim -r -l '  a b  ' # "a b"

trim 'x' 'xa bx'         # "a b"
trim 'x' 'xxa bxx'       # "a b"
trim -l 'x' 'xxa bxx'    # "a bxx"
trim -r 'x' 'xxa bxx'    # "xxa b"
trim -r -l 'x' 'xxa bxx' # "a b"

trim -l 'xy' 'xyxya bxyxy' # "a bxyxy"
trim -r 'xy' 'xyxya bxyxy' # "xyxya b"
trim 'xy' 'xyxya bxyxy'    # "a b"
trim 'xy' 'a b'            # "a b"
trim -v var 'xy' 'xyxyab'   # var="ab"

squash

squash [-v Var] [-s] [Target] str

压缩字符串str中指定的连续目标字符。

  • -v Var表示将压缩后的字符串赋值给变量Var,否则压缩后的字符串将被输出
  • -s表示不先移除前缀连续和后缀连续目标字符后再压缩。不指定该选项时,将先移除前缀和后缀连续目标字符,然后再压缩
  • Target表示压缩字符串中的哪个连续字符,如果该选项超过一个字符,则只有第一个字符被当作目标字符

例如:

squash  '  a  b  c  '        # "a b c"
squash -s '  a  b  c  '      # " a b c "
squash "," ',,,a,,b,,c,,'    # "a,b,c"
squash -s "," ',,,a,,b,,c,,' # ",a,b,c,"
squash -s ",-" ',,-a,,--b,,c,,' # ",-a,--b,c,"

split

split -v Arr [Sep] String

根据指定分隔符Sep,将字符串String划分为多个部分后保存到数组Arr中。

当未指定分隔符Sep时,默认按照空格划分字符串。且在划分之前,会执行如下两个步骤:

  • 移除String中前缀和后缀的连续分隔符
  • String中出现的连续分隔符总是先被压缩到单个分隔符

例如:

split -v arr 'x' 'xxabcxdefxghixjklxx'
#=> arr=(abc def ghi jkl)
split -v arr1 ' abc  def  ghi  jkl  '
#=> arr1=(abc def ghi jkl)

index和index_all

index [-v Var] [-r] Substr String
index_all [-v Arr] Substr String

index搜索字符串String中第一次出现子串Substr的索引位置,默认从左向右搜索。指定-r选项表示从右向左搜索。如果String中未搜索到Substr,则以-1表示索引值。指定-v Var可将搜索到的索引值(包括未搜索到时的-1索引值)赋值给变量Var,否则将输出。

index_all搜索字符串String中所有Substr出现的索引位置,默认将输出这些索引值,指定-v Arr表示将这些索引值保存到数组Arr。如果String中未搜索到Substr,则输出空或保存为空数组。

例如:

# 从左向右搜索第一次出现的子串
index 'ab' 'abcdab'      # 0
index 'ab' 'ABabcdab'    # 2
index 'a b' 'ABa bcdab'  # 2
index 'a b' 'ABabcdab'   # -1

# 从右向左搜索第一次出现的子串
index -r 'ab' 'abcd'     # 0
index -r 'ab' 'abcdab'   # 4
index -r 'a b' 'abcda b' # 4
index -r 'a b' 'abcdab'  # -1

# 搜索所有子串出现的索引位置
index_all 'ab' 'abcdab'    # `0 4' or '(0 4)'
index_all 'ab' 'abcdabab'  # `0 4 6' or '(0 4 6)'
index_all 'abx' 'def'      # '' or ()

chars

chars [-v Arr] Str

将字符串每个字符保存到数组Arr,如果未指定-v Arr,则以(x y z)的字符串格式输出各字符。

例如:

chars 'abcd'  # (a b c d)
chars -v arr 'abcd'  # arr=(a b c d)

str_slice

str_slice [-v Var] Str         # (1)
str_slice [-v Var] M..N Str    # (2)
str_slice [-v Var] N [Len] Str # (3)

获取字符串Str的切片(即子串)。指定-v Var选项时,表示将获取到的子串赋值给变量Var,否则将输出子串。

对于语法(1),表示获取Str的所有字符,即Str的副本。

对于语法(2),表示获取Str中指定范围的字符。支持的范围语法包括M..N, ..N, M..。M和N代表索引,它们可以是负数,表示从右向左的索引,-1表示倒数第一个字符,-2表示倒数第二个字符。但要注意,指定的范围是合法的,不允许M代表的索引位置在N代表的索引位置的右边。

对于语法(3),表示从索引位置N处开始,获取长度为Len的子串。N可以为负数,表示从右向左计算负数索引位置。如果省略Len参数,表示获取从N开始的剩余所有字符。Len也可以为负数,此时它不表示长度,而是表示获取的终止索引位置,且从右向左计算负数索引位置。

例如:

test_str__="01234567890abcdefgh"
str_slice "${test_str}"       # "01234567890abcdefgh"

str_slice 1..3 "${test_str}"  # "123"
str_slice 7.. "${test_str}"   # "7890abcdefgh"
str_slice ..7 "${test_str}"   # "01234567"
str_slice 1..-7 "${test_str}" # "1234567890ab"
str_slice -7.. "${test_str}"  # "bcdefgh"
str_slice ..-7 "${test_str}"  # "01234567890ab"
str_slice -10..-7 "${test_str}"  # "90ab"

str_slice 7 "${test_str}"     # "7890abcdefgh"
str_slice 7 0 "${test_str}"   # ""
str_slice 7 2 "${test_str}"   # "78"
str_slice 7 -2 "${test_str}"  # "7890abcdef"
str_slice -7 "${test_str}"    # "bcdefgh"
str_slice -7 2 "${test_str}"  # "bc"
str_slice -7 -2 "${test_str}" # "bcdef"

random_str

random_str [-v Var]
random_str [-v Var] [N]
random_str [-v Var] [-lupn] [N]

不指定-v Var选项时,生成的随机字符串将被输出,指定-v Var时,随机字符串将不会被输出而是被赋值给指定的shell变量Var。

N表示生成的随机字符串长度,省略N时,默认N=8。

-lupn选项中的l u p n分别表示:

  • l:将小写字母a-z放入随机字符串的生成源
  • u:将大写字母A-Z放入随机字符串的生成源
  • n:将数字0-9放入随机字符串的生成源
  • p:将标点符号放入随机字符串的生成源

它们可以单独使用,比如random_str -l 8将生成8位小写字母的随机字符串。它们也可以结合使用,例如random_str -ln 8将生成8位小写字母、数字组成的随机字符串。当省略该选项时,等价于-lunp

注意,当结合使用时,不会保证生成的随机字符串中一定包含指定的字符。例如-ln选项生成的随机字符串中,可能只有数字,可能只有小写字母,也可能包含两者。使用一个选项只是将这类字符加入随机字符串的生成源,生成随机字符串时不一定会选中这类字符。

例如:

random_str 5   # 输出由大小写字母、数字、标点组成的5位随机字符串
random_str -l 5  # 输出由小写字母组成的5位随机字符串
random_str -lu 5  # 输出由大小写字母组成的5位随机字符串
random_str -v var -lu 5  # 将由大小写字母组成的5位随机字符串赋值给变量var而不是输出

About

some useful lib function for bash(一些有用的shell函数库)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages