我的测试基本都是在Mac,及Unix环境下测试的,如无特别注明,默认就是Mac
不论你看到这篇随笔是被shell array的奇淫巧技,还是发现shell array就在一对{}里面就可以做那么多勾当,然而记不清楚了,当然有可能发现不管是用$*还是$@数组长度都是1,这可怎么办,还是小白,我就从我碰壁的过程中得到的碎屑整理一二,打通你的任督二脉
Shell是有很多种的
以Bash为标准来说明
A数组创建
无非就是2中几乎所有的编程语言都有的方法,一种单个赋值,一种是一起()赋值(1,2)。还有两种不正常的(3,4)
B复制数组
#记得这对括号,只要字符串是以空格分隔的,加一对括号,就变数组,Perl的匿名数组和哈希就用的这套思路
# 加不加括号数组长度一样,但是不加的话,数组的第一个值变成了真个数组的字符串,有用的track就是定义数组的时候array[0]空着,从array[1]开始
C数组下标系统
D数组和各元素长度
举个例子来验证一下我说的长度和下标,下面4种分贝对应A创建数组部分的4中形式,
1 array_str="ubuntu deepin elementory opensuse fedora centos" 2 array_ot[0]=ubuntu;array_ot[1]=deepin;array_ot[2]=elementory;array_ot[3]=opensuse;array_ot[4]=fedora;array_ot[5]=centos 3 array_ar=(ubuntu deepin elementary opensuse fedora centos) 4 array_bl=([0]=ubuntu [1]=deepin [2]=elementory [3]=opensuse [4]=fedora [5]=centos) 5 6 array_fstr=($array_str)
然后看一下各种定义数组的长度时候一样,以及第1个和第2个元素是什么
1 echo *********************Length********************* 2 echo -e array_str@,${#array_str[@]},"\t${array_str[0]}>>>${array_str[1]}" 3 echo -e array_fstr*,${#array_fstr[*]},"\t${array_fstr[0]}>>>${array_fstr[1]}" 4 echo -e array_ot,${#array_ot[@]},"\t${array_ot[0]}>>>${array_ot[1]}" 5 echo -e array_ar,${#array_ar[@]},"\t${array_ar[0]}>>>${array_ar[1]}" 6 echo -e array_bl,${#array_bl[@]},"\t${array_bl[0]}>>>${array_bl[1]}"
结果如下,说明4重情况长度都是正常计算的
从结果就可以看出,字符串按数组方式引用的话,就被看作一个元素的数组(array_str),而加了括号之后,就被转换成数组(array_fstr),说明四种都可以的
然后在验证函数中的情况,虽大同,但也有小异
我们来写一个函数,验证$*和$@的不同,以及复制数组是否一致
和整个shell脚本一样,函数也可以用位置变量来引用,$1,$2,$3,$4, ... ...
1 function say(){ 2 echo -e " ****************From say\033[00m"
3 echo -e "Length \$@ ",${#@},"\t$1>>>$2"
4 echo -e "Length \$* ",${#*},"\t$1>>>$2"
5 args=($@) 6 echo -e "\033[01;32m>>>>>>>>> args=(\$@)\033[00m"
7 echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
8 echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
9 args=$@ 10 echo -e "\033[01;32m>>>>>>>>> args=\$@\033[00m"
11 echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
12 echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
13 args=($*) 14 echo -e "\033[01;32m>>>>>>>>> args=(\$*)\033[00m"
15 echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
16 echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
17 args=$*
18 echo -e "\033[01;32m>>>>>>>>> args=\$*\033[00m"
19 echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
20 echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
21 } 22
23 echo -ne "\033[01;31m=================> \${array_ar[@]}"
24 say ${array_ar[@]} 25 echo -ne "\033[01;31m=================> $array_str"
26 say $array_str
结果分析就是,无论是$*还是$@在复制到新array中的时候都要加括号,不然第一个元素被整个数组字符串覆盖,我们由此想,把第一个元素的位置空出来不就行了吗?但是我还不知道怎么弄
admin@iMac:~ => array_ar=("ubuntu" "deepin" "elementary" "opensuse" "fedora" "centos");n=${#array_ar[@]};for ss in `seq 0 $n`;do echo -e "$ss\t${array_ar[$ss]}\t"${#array_ar[$ss]}; done 0 ubuntu 6 1 deepin 6 2 elementary 10 3 opensuse 8 4 fedora 6 5 centos 6 6 0
E数组切片
用习惯了Perl的数组分片,Perl从Bash借鉴了很多东西来
F元素字符(串)替换/删除
Fig G.1
Fig G.2
H元素字符(串)删除
Fig H.1
Fig H.2
Fig H.3
既然字符串可以看作是单个元素的数组,那上面这一套都适合Bash中的字符串处理
Reference:
1. http://bbs.chinaunix.net.sixxs.org/thread-1779167-1-1.html
2. http://www.cnblogs.com.sixxs.org/chengmo/archive/2010/09/30/1839632.html
3. 鸟哥的Linux私房菜 基础版 (第三版)
4. http://en.wikipedia.org/wiki/Tcsh