我的测试基本都是在Mac,及Unix环境下测试的,如无特别注明,默认就是Mac

不论你看到这篇随笔是被shell array的奇淫巧技,还是发现shell array就在一对{}里面就可以做那么多勾当,然而记不清楚了,当然有可能发现不管是用$*还是$@数组长度都是1,这可怎么办,还是小白,我就从我碰壁的过程中得到的碎屑整理一二,打通你的任督二脉


Shell是有很多种的

  • /bin/sh (已经被 /bin/bash 所取代)
  • /bin/bash (就是 Linux预设shell,bash 主要兼容sh,而且依据一些使用者需求而加强的shell 版本)
    • 一般认为是1979年, Stephen Bourne发明的,他为UNIX写了第一个主要的shell程序,并命名为Bourne Shell,后来几乎所有的UNIX的shell都是源自它,后来一个新的加强版的逐渐成熟,成为Bourne Again Shell (Bash),在继承"老版"sh的基础上添加了很多功能,一般这个加强或者扩充是Brian Fox以及Chet Ramey完成的
  • /bin/csh (已经被 /bin/tcsh 所取代)
    • 与Bourne Shell同时,University of California, Berkeley的Bill Joy提出了C Shell的思想,Joy认识到Bourne shell的不足(无法后台运行),决定用C语言中的保留字设计C Shell。
  • /bin/ksh (Kornshell 由 AT&T Bell lab. 开发出来的,兼容bash的)
    • 与csh同时,贝尔实验室的David Korn也发明了Korn Shell 来修复C Shell中的不足,并且完全兼容Bourne Shell,而且ksh新版本还提供window功能。
  • /bin/tcsh (整和 C Shell ,提供更多的功能)
    • 1975年, Carnegie Mellon University的Ken Greer受TENEX操作系统启发开始实现Tenex-style文件名补全功能,1981年整合C Shell 然后1983年 Mike Ellis有加入了命令补全功能,最终在1983年发布。
  • /bin/zsh (基于 ksh发展出来的,功能更强大的shell)
    • 是1990年princeton University的一个学生Paul Falstad写的第一版

以Bash为标准来说明

A数组创建

无非就是2中几乎所有的编程语言都有的方法,一种单个赋值,一种是一起()赋值(1,2)。还有两种不正常的(3,4)

  1. array[0]=one;array[1]=two;array[2]=three # 0-based
  2. array=(one two three) #用空格分隔开来
  3. array=([0]=one [1]=two [2]=three) #用空格分隔开来,0-based
  4. array="one two three" #也是可以的,这样就把bash array的本质暴露出来了,就是个字符串

B复制数组

  1. new_array=($old_array_name)
  2. new_array=${old_array_name[@]}
  3. new_array=${old_array_name[*]}
  • new_array=($@) #如果在函数中的话,只有B.1这种,因为$@无法写成${@[@]}

#记得这对括号,只要字符串是以空格分隔的,加一对括号,就变数组,Perl的匿名数组和哈希就用的这套思路

# 加不加括号数组长度一样,但是不加的话,数组的第一个值变成了真个数组的字符串,有用的track就是定义数组的时候array[0]空着,从array[1]开始

C数组下标系统

  • ${array[index]} #绝大多数语言的index都是0-based,Shell也支持0-based

D数组和各元素长度

  • ${#array[@]} #数组元素的个数
  • ${#array[*]}  #数组元素的个数
  • ${#array[n]}  #第n个元素的字符串长度

举个例子来验证一下我说的长度和下标,下面4种分贝对应A创建数组部分的4中形式,

 array_str="ubuntu deepin elementory opensuse fedora centos"
array_ot[]=ubuntu;array_ot[]=deepin;array_ot[]=elementory;array_ot[]=opensuse;array_ot[]=fedora;array_ot[]=centos
array_ar=(ubuntu deepin elementary opensuse fedora centos)
array_bl=([]=ubuntu []=deepin []=elementory []=opensuse []=fedora []=centos) array_fstr=($array_str)

然后看一下各种定义数组的长度时候一样,以及第1个和第2个元素是什么

 echo *********************Length*********************
echo -e array_str@,${#array_str[@]},"\t${array_str[0]}>>>${array_str[1]}"
echo -e array_fstr*,${#array_fstr[*]},"\t${array_fstr[0]}>>>${array_fstr[1]}"
echo -e array_ot,${#array_ot[@]},"\t${array_ot[0]}>>>${array_ot[1]}"
echo -e array_ar,${#array_ar[@]},"\t${array_ar[0]}>>>${array_ar[1]}"
echo -e array_bl,${#array_bl[@]},"\t${array_bl[0]}>>>${array_bl[1]}"

结果如下,说明4重情况长度都是正常计算的

从结果就可以看出,字符串按数组方式引用的话,就被看作一个元素的数组(array_str),而加了括号之后,就被转换成数组(array_fstr),说明四种都可以的

然后在验证函数中的情况,虽大同,但也有小异

我们来写一个函数,验证$*和$@的不同,以及复制数组是否一致

和整个shell脚本一样,函数也可以用位置变量来引用,$1,$2,$3,$4, ... ...

 function say(){
echo -e " ****************From say\033[00m"
echo -e "Length \$@ ",${#@},"\t$1>>>$2"
echo -e "Length \$* ",${#*},"\t$1>>>$2"
args=($@)
echo -e "\033[01;32m>>>>>>>>> args=(\$@)\033[00m"
echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
args=$@
echo -e "\033[01;32m>>>>>>>>> args=\$@\033[00m"
echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
args=($*)
echo -e "\033[01;32m>>>>>>>>> args=(\$*)\033[00m"
echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
args=$*
echo -e "\033[01;32m>>>>>>>>> args=\$*\033[00m"
echo -e "Length \$args*",${#args[*]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
echo -e "Length \$args@",${#args[@]},"\t${args[0]}>>>${args[1]}>>>${args[2]}"
} echo -ne "\033[01;31m=================> \${array_ar[@]}"
say ${array_ar[@]}
echo -ne "\033[01;31m=================> $array_str"
say $array_str

结果分析就是,无论是$*还是$@在复制到新array中的时候都要加括号,不然第一个元素被整个数组字符串覆盖,我们由此想,把第一个元素的位置空出来不就行了吗?但是我还不知道怎么弄

admin@iMac:~ => array_ar=("ubuntu" "deepin" "elementary" "opensuse" "fedora" "centos");n=${#array_ar[@]};for ss in `seq  $n`;do echo -e "$ss\t${array_ar[$ss]}\t"${#array_ar[$ss]}; done
ubuntu
deepin
elementary
opensuse
fedora
centos

E数组切片

用习惯了Perl的数组分片,Perl从Bash借鉴了很多东西来

  • ${array:m} #切处第m个元素(included)开始的所有元素切片,为字符串,赋值都是字符串
  • ${array:m:n} #切处第m个元素(included)开始n个元素的切片,为字符串,赋值都是字符串
  • new_slice=({array:m:n})

F元素字符(串)替换/删除

  • 第一个

    • ${array[n|@|*]/what/replacement} #把第n+1个元素/所有元素匹配到what的把what字符(串)替换成replacement,并不会对原数组改变
    • new_array=${array[@]/what/replacement}
    • new_element=${array[n]/what/replacement}
    • 简单说就是:会对你没个指定的元素执行what->replacement的替换,但是只会对每个元素中what第一次出现的位置进行替换,如果某个元素字符串含有多个what字符(串),则只替换第一个
  • 全局的
    • ${array[n|@|*]//what/replacement} # 把第n+1个元素/所有元素匹配到what的把what字符(串)替换成replacement,并不会对原数组改变
    • new_array=${array[@]//what/replacement}
    • 简单说就是:会对你没个指定的元素执行what->replacement的替换,但是会对每个元素中每个出现what的位置都进行替换,即使某个元素字符串含有多个what字符(串),也都会被替换掉
  • replacement为空即为删除,不支持通配符匹配

Fig G.1

Fig G.2

H元素字符(串)删除

  • 可以使用通配符*(元字符)
  • ${array[n|@|*]#pattern}     #删除每个元素中符合pattern的部分,匹配最短,如pattern为u*n,元素为ubunbunbuntu的话,则切的是ubun,留的是bunbuntu, Fig H.1
  • ${array[n|@|*]##pattern}   #删除每个元素中符合pattern的部分,匹配最长,如pattern为u*n,元素为ubunbunbuntu的话,则切的是ubunbunbun,留的是tu, Fig H.1
  • ${array[n|@|*]%pattern}    #删除每个元素中符合pattern的部分,匹配最短,如pattern为n*u,元素为ubunbunbuntu的话,则切的是ntu,留的是ubunbunbu, Fig H.2
  • ${array[n|@|*]%%pattern} #删除每个元素中符合pattern的部分,匹配最长,如pattern为n*u,元素为ubunbunbuntu的话,则切的是nbunbuntu,留的是ubu, Fig H.2
  • 千万注意:限制是必须匹配某一头,#时必须匹配开头,%是=时必须匹配末尾,就是你必须从某一头连续切,不能在中间切一段, Fig H.3

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

Linux, Mac下Shell 数组 Array 的修理工的更多相关文章

  1. Mac下Shell脚本使用学习笔记(一)

    参考文献 Shell 教程 MAC常用终端命令行 Mac下Shell脚本使用 1.使用终端创建test.sh: (1)进入指定文件夹路径(命令示例:cd Desktop/面向对象程序设计): (2)创 ...

  2. linux/mac下的配置自定义命令alias

    linux/mac下的自定义命令alias,并保存别名使其永久生效(重启不会失效) 在做开发每次提交代码的命令都是一长串参数,不想去记,于是可以使用alias命令来解决这个问题:alias aComm ...

  3. Mac下Shell脚本使用学习笔记(二)

    参考文献 Shell 教程 MAC常用终端命令行 Mac下Shell脚本使用 (7)Shell echo命令: 命令格式:echo string ①显示普通字符串:echo "It is a ...

  4. linux/mac下命令行rm回收站--rmtrash

    Linux.mac的命令行下没有回收站功能,很多时候手一抖就把重要文件给 rm -fr * 了,虽然linux下有可能通过lost +found/debugfs找回,但难度也比较大,不能保证一定能够找 ...

  5. Linux环境下shell和vim中乱码原因及消除办法

    shell和vim中乱码原因及消除办法 作者:Jack47 在Linux下开发,经常遇到乱码问题:shell或者vim中显示不了中文,或者能够显示,但不能输入中文.每次都是上网去搜,或者同事告诉我一些 ...

  6. linux,Mac下lu 一把

    习惯Terminal没有不知道ls命令的(等同于DOS的dir),经常只是需要查看目录的内容大小,但ls -h显示的只是目录的本身大小,而且很多项内容 ls 在这方面的两个诟病出现了: 小诟1. 显示 ...

  7. Linux学习笔记 -- Shell 数组

    定义 在Shell的世界里,我们只能定义一维数组. 定义数组的时候不需要指定长度,数组的下标从0开始; Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下: sh ...

  8. 【原】Linux环境下Shell调用MySQL并实现定时任务

    对于一些周期性事务,我们可以在Linux下,使用shell脚本调用mysql数据库存储过程,并设置定时任务. 本来是要mysql数据库中创建事件任务来,定时执行存储过程,做数据传输的...使用cron ...

  9. windows/Linux/Mac下安装maven,maven作用

    Linux下安装maven 1.首先到Maven官网下载安装文件,目前最新版本为3.0.3,下载文件为apache-maven-3.3.9-bin.tar.gz,下载可以使用wget命令: 2.进入下 ...

随机推荐

  1. PHP登陆Session验证

    关键字:PHP Session 登陆 验证 本文地址:http://www.cnblogs.com/txw1958/p/php-login-check-session.html 首先,在MySQL数据 ...

  2. you need to upgrade the working copy first

    is too old (format 29) to work with client version '1.9.4 (r1740329)' (expects format 31) 2016年09月18 ...

  3. Scanner类的使用

    Scanner类的使用 (接受键盘输入) java.util.Scanner是Java5的新特征,主要功能是简化文本扫描.这个类最实用的地方表现在获取控制台输入,其他的功能都很鸡肋,尽管Java AP ...

  4. Thread 线程

    线程 Join 一线程里面调用另一线程join方法时,表示将本线程阻塞直至另一线程终止时再执行 using System.Linq; using System.Text; using System.T ...

  5. HBase环境搭建

    HBase与Hadoop对应关系:http://hbase.apache.org/book.html#basic.prerequisites   4.1. Hadoop 这块介绍了对应关系 HBase ...

  6. 解决Regsvr32: DllRegisterServer entry point was not found

    原因: 虽然项目里面包含了DEF文件, 但是尼玛没有配置项目属性让链接器处理它啊! 解决方案: 项目属性->链接器->输入->模块定义文件->{输入文件名}

  7. 主机OS重装的节点加回RAC集群步骤示例(11gR2 RAC)

    原文地址: https://blogs.oracle.com/Database4CN/entry/%E4%B8%BB%E6%9C%BAos%E9%87%8D%E8%A3%85%E7%9A%84%E8% ...

  8. mysql explain 命令讲解

    explian命令可以显示select语句的执行计划 explain的结果中每行对应select语句中的一个表,输出结果中的顺序是按照语句处理表的顺序. mysql使用嵌套循环来处理所有的join连接 ...

  9. 单链表的回文判断(O(n)时间复杂度和O(1)的空间复杂度)

    对于单链表来说,判断回文最简单的方法就是遍历链表,将链表中的元素复制到数组中,然后对数组进行判断是否是回文数组,但是这不符合O(1)的空间复杂度. 由于空间复杂度的要求,需要就地操作链表,不能开辟多余 ...

  10. HTML_css样式表 样式属性 格式布局

    CSS(Cascading Style Sheet,叠层样式表),作用是美化HTML网页. /*注释区域*/此为注释语法 一.样式表 (一)样式表的分类 1.内联样式表 和HTML联合显示,控制精确, ...