我的测试基本都是在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. less 命令(转)

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...

  2. SQLServer 统计数据量

    做一个项目,第一件事情就是问:“这个数据库多大?” 下面是统计数据库数据量大小的方法 通常我们会使用命令: "sp_helpdb @dbname" 例如,查询数据库"te ...

  3. UIlabel多行文字自动换行 (自动折行)

    UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(, , , )]; UILabel *label = [[UILabel al ...

  4. ASP.NET easyUI--datagrid 通过ajax请求ASP.NET后台数据的分页查询

    js前台对datagrid的定义代码,如下 mygrid = $('#mytable').datagrid({ fit: true, //自动大小 height: 'auto', rownumbers ...

  5. 电量显示Binding Converter MVVM

    用一个ProcessBar显示电量,低于20%时候,ForeGround为红色,否则为绿色, 页面使用了MVVM绑定到了ViewModel, ProcessBar XAML为 <Progress ...

  6. iOS UITableView点击按钮滚到顶部

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

  7. MYBATIS报ORA-01745: 无效的主机/绑定变量名 异常

    异常:Cause: java.sql.SQLSyntaxErrorException: ORA-01745: 无效的主机/绑定变量名 原因,sql语句中,两个填充变量间没有写逗号.

  8. tomcat下jndi配置

    jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用 ...

  9. jQuery uploadify上传文件404,500错误

    1.如果部署到了IIS7的话,IIS7默认的大小为3000000.修改方法如下: 找到网站双击“请求筛选”——右边找到“编辑功能设置”——将“允许的最大内容长度”改成你想要的就行了. 2.当上传大文件 ...

  10. ios app 解决微信扫二维码不能跳转问题

    <script> (function(){ // Setup GA (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i ...