shell浅谈之十一别名、列表及数组
一、简介 Shell中别名可以对命令进行重新命名,方便用户记忆长命名和定制自己熟悉的工作环境;列表是一组命名以逻辑与、逻辑或的关系串在一起,实现脚本程序的逻辑控制;数组是一重点,涉及数组的赋值、操作和字符串的处理,以及利用数组实现堆栈和二维数组等数据结构的存储。二、详解1、别名 对linux命令重新命名,主要考虑到很多linux命令带有冗长的选项
一、简介
Shell中别名可以对命令进行重新命名,方便用户记忆长命名和定制自己熟悉的工作环境;列表是一组命名以逻辑与、逻辑或的关系串在一起,实现脚本程序的逻辑控制;数组是一重点,涉及数组的赋值、操作和字符串的处理,以及利用数组实现堆栈和二维数组等数据结构的存储。
二、详解
1、别名
对linux命令重新命名,主要考虑到很多linux命令带有冗长的选项和参数,频繁使用这些长命令极易造成用户使用上的不便。别名的命令关键字是alias,基本格式为alias name='original-command'(等号两边不能有空格)。如alias ipconfig=ifconfig。若要删除已经设置的别名,使用内建命令unalias,unalias -a表示删除所有已设置的别名,unalias alias-name表示仅删除alias-name别名。
- #!/bin/bash
- shopt -s expand_aliases #打开expand_aliases选项
- alias detail="ls -l"
- detail /root/in* #别名支持通配符*
- echo
- directory=/root/
- prefix=in*
- alias vardetail="ls -l $directory$prefix" #双引号和单引号在处理空格时是等价的,
- #但设置vardetail引用了变量,此处只能使用双引号
- vardetail
- echo "Deleting all aliases:"
- unalias -a #删除所有的别名
- detail
- vardetail
要注意的是:在诸如if/then结构、循环和函数等混合型结构中不能使用alias命令设置别名,但可以执行在混合型结构之外所设置的别名。
2、列表
(1)shell中列表是由一串命令用与运算(&&)和或运算(||)连接而成,分别称为与列表和或列表。与列表的格式为:命令1 &&命令2&&命令3 &&...&&命令n,从左到右依次执行命名,直到某命令返回FALSE时(退出状态为非0)与列表执行终止。或列表的格式为:命令1 || 命令2 ||命令3 ||...||命令n,从左到右依次执行命名,但是当某命令返回TRUE时(退出状态为0)或列表执行终止。
(2)与列表控制输入参数个数和返回状态码
- #!/bin/bash
- MAXARGS=3
- ERROR=68
- test $# -ne $MAXARGS && echo "Usage: `basename $0` $MAXARGS arguments" && exit $ERROR
- echo "Less than $MAXARGS arguments are passed to this script."
- exit 0
(3)或列表控制输入参数个数和返回状态码
- #!/bin/bash
- MAXARGS=3
- ERROR=68
- test $# -eq $MAXARGS || (echo "Usage: `basename $0` $MAXARGS arguments" && false) || exit $ERROR
- echo "Correct arguments are passed to this script."
- exit 0
3、数组
(1)赋值和取值
数组(Array)是一个由若干同类型变量组成的集合,数组均由连续的存储单元组成,最低地址对应于数组的第一个元素,最高地址对应于最后一个元素。Shell只支持一维数组,array[x]表示array数组的第x+1个元素,支持的最大数值标号是599 147 937 791。shell取得数组值(引用数组元素)格式是:${array[x]}。
- #!/bin/bash
- city[0]=Nanjing #对第1、2个数组元素赋值
- city[1]=Beijing
- city[9]=Melbourne #对第10个数组元素赋值
- city[15]=NewYork #对第16个数组元素赋值
- echo "city[0]=${city[0]}"
- echo "city[1]=${city[1]}"
- echo "city[9]=${city[9]}"
- echo "city[15]=${city[15]}"
- echo "city[2]=${city[2]}" #未初始化数组的值为空
- echo "city[10]=${city[10]}"
Shell中允许数组空缺元素,即可以不连续地给数组赋值。还可以用圆括号将一组值赋给数组。
- #!/bin/bash
- city=(Nanjing Beijing Melbourne NewYork) #圆括号内以空格为分隔符,依次赋给数组元素
- echo "city[0]=${city[0]}"
- echo "city[1]=${city[1]}"
- echo "city[2]=${city[2]}"
- echo "city[3]=${city[3]}"
- echo "city[4]=${city[4]}" #未被初始化输出空
- echo "city[5]=${city[5]}"
- #!/bin/bash
- city=(Nanjing [10]=Atlanta Massachusetts Marseilles) #指定所赋元素的标号,并以此标号为起点继续赋值
- echo "city[0]=${city[0]}" #city[0]=Nanjing
- echo "city[1]=${city[1]}" #city[1]=
- echo "city[10]=${city[10]}" #city[10]=Atlanta
- echo "city[11]=${city[11]}" #city[11]=Massachusetts
- echo "city[12]=${city[12]}" #city[12]=Marseilles
- echo "city[13]=${city[13]}" #city[13]=
- city=([2]=Nanjing [10]=Atlanta [1]=Massachusetts [5]=Marseilles)
- #!/bin/bash
- city=(Nanjing Beijing Melbourne NewYork)
- for i in ${city[@]} #等价于 for i in ${city[*]}
- do #打印数组的所有元素
- echo $i
- done
- #!/bin/bash
- city[1]="Hong Kong" #用引号包含空格的字符串
- city[100]=Massachusetts
- city[101]="New York"
- city[10000]=Atlanta
- for i in "${city[@]}"
- do
- echo $i
- done
注意:"${city[@]}"将数组的所有元素分行打印,而"${city[*]}"只能将数组的所有元素打印在一行内且中间以IFS分隔。不用引号时${city[@]}和${city[*]}是等价的,使用引号时,@和*只是打印数组的方式存在差异。
(3)数组的用法
数组的字符串操作与字符串操作的符号和意义完全一致,数组字符串操作特殊之处在于所有的操作都是针对所有的数组元素逐个进行的。
- #数组的字符串操作
- #!/bin/bash
- city=(Nanjing Atlanta Massachusetts MaseillesMas)
- echo "Extracting Substring" #抽取字串
- echo ${city[*]:0} #抽取整个数组 Nanjing Atlanta Massachusetts Marseilles
- echo ${city[*]:1} #抽取从第1个元素到结束的数组 Atlanta Massachusetts Marseilles
- echo ${city[*]:3} #抽取从第3个元素到结束的数组 Marseilles
- echo ${city[*]:0:2} #抽取从第0个元素开始的两个元素 Nanjing Atlanta
- echo
- echo "Removing Substring" #删除字串
- echo ${city[*]#M*a} #删除匹配M*a的最短字串 Nanjing Atlanta ssachusetts rseilles
- echo ${city[*]##M*a} #删除匹配M*a的最长字串 Nanjing Atlanta chusetts rseilles
- echo
- echo "Replcing Substring" #替换子串功能
- echo ${city[*]/M*s/Year} #替换第1次与M*a匹配的子串 Nanjing Atlanta Year Year
- echo ${city[*]//Mas/Year} #替换所有与Mas匹配的子串 Nanjing Atlanta Yearsachusetts YeareillesYear
- #替换的正则为最长匹配
shell数组的一种重要操作:数组连接。
- #!/bin/bash
- city=(Beijing Nanjing Shanghai)
- person=(Cai [5]=Wu Tang) #数组不连续地赋值
- declare -a combine #声明combine数组
- combine=(${city[@]} ${person[@]}) #combine是数组city和person的连接,连接操作将不连续的元素按序存放到combine数组中
- element_count=${#combine[@]} #while循环输出combine数组
- index=0
- while [ "$index" -lt "$element_count" ]
- do
- echo "Element[$index]=${combine[$index]}" #数组标号与值的对应关系
- let "index=$index+1"
- done
- ###################
- echo
- unset combine #清空combine数组
- combine[0]=${city[@]} #将city数组赋给combine[0]的一个元素
- combine[1]=${person[@]} #将person数组赋给combine[1]的一个元素
- element_count=${#combine[@]}
- index=0
- while [ "$index" -lt "$element_count" ]
- do
- echo "Element[$index]=${combine[$index]}"
- let "index=$index+1"
- done
- ###################
- echo
- declare -a subcombine=${combine[1]} #声明数组时赋值
- element_count=${#subcombine[@]}
- index=0
- while [ "$index" -lt "$element_count" ]
- do
- echo "Element[$index]=${subcombine[$index]}"
- let "index=$index+1"
- done
(4)数组实现简单的数据结构
数据结构是指相互之间存在一种或多种特定关系的数据元素的集合,它直接影响到程序的运行速度和存储效率。Shell不直接支持如堆栈、队列、链表等数据结构,但可以很容易实现线性数据结构。对于树形、图等复杂的数据结构,shell理论上可以实现,但难度角度。
利用数组实现堆栈操作。push函数将字符串压入堆栈,pop函数能弹出栈顶元素,status函数打印当前堆栈的状态信息。其中shift命令完成两个功能:第一,所有位置参数左移1位,即$2移动到$1的位置,$3移动到$2的位置,依次类推($0不变);第二,$#变量值减1。
- #!/bin/bash
- MAXTOP=50 #堆栈能存放元素的最大值
- TOP=$MAXTOP #栈顶指针,初始值是$MAXTOP
- TEMP=
- declare -a STACK #全局数组STACK
- push() #push进栈操作,可同时将多个元素压入堆栈
- {
- if [ -z "$1" ] #无参数,返回
- then
- return
- fi
- #for ((i=1; i<=$#; i++))
- until [ $# -eq 0 ] #until循环将push函数的所有参数都压入堆栈
- do
- let TOP=TOP-1 #栈顶指针减1
- STACK[$TOP]=$1
- shift #脚本参数除$0外左移1位,$#参数总个数减1
- done
- return
- }
- pop() #pop出栈操作,执行pop函数使栈顶元素出栈
- {
- TEMP=
- if [ "$TOP" -eq "$MAXTOP" ] #若堆栈为空,返回
- then
- return
- fi
- TEMP=${STACK[$TOP]} #栈顶元素出栈
- unset STACK[$TOP]
- let TOP=TOP+1 #栈顶指针加1
- return
- }
- status() #显示当前堆栈内的元素,以及TOP指针和TEMP变量
- {
- echo "==========STACK=========="
- for i in ${STACK[@]}
- do
- echo $i
- done
- echo "Stack Pointer=$TOP"
- echo "Just popped \""$TEMP"\" off the stack"
- echo "=========================="
- }
- push one #1个元素入栈
- status #显示状态
- push two three four #3个元素入栈
- status
- pop #出栈
- pop
- status
- push five six
- status
利用一维数组模拟实现二维数组,二维数组仍存储在一维数组中,只是通过行号和列号计算出数组的索引而已。可以采用该方法使shell脚本语言用于定义二维数组和矩阵。
- #创建一个二维数组,并以逐行打印及旋转45度打印的两种方式将它打印出来
- #!/bin/bash
- #定义行数、列数,及数组名
- ROW=5
- COL=5
- declare -a MATRIX #申明MATRIX数组
- load_alpha ()
- {
- local rc=0
- local index
- #for循环将A-Y这25个字符存储到MATRIX数组
- for i in A B C D E F G H I J K L M N O P Q R S T U V W X Y
- do
- local row=`expr $rc / $COL`
- local column=`expr $rc % $ROW`
- let "index = $row * $ROW + $column"
- MATRIX[$index]=$i
- let "rc += 1"
- done
- }
- print_alpha ()
- {
- local row=0
- local index
- #逐行打印MATRIX数组
- while [ "$row" -lt "$ROW" ]
- do
- local column=0
- echo -n " "
- while [ "$column" -lt "$COL" ]
- do
- let "index = $row * $ROW + $column"
- echo -n "${MATRIX[index]} "
- let "column += 1"
- done
- let "row += 1"
- echo
- done
- echo
- }
- filter () # 过滤掉负的数组下标.
- {
- echo -n " " # 产生倾斜.
- # 解释一下, 这是怎么做到的.
- if [[ "$1" -ge 0 && "$1" -lt "$ROW" && "$2" -ge 0 && "$2" -lt "$COL" ]]
- then
- let "index = $1 * $ROW + $2"
- # 现在, 按照旋转方向进行打印.
- echo -n " ${MATRIX[index]}"
- # alpha[$row][$column]
- fi
- }
- rotate () # 将数组旋转45度 --
- { #+ 从左下角进行"平衡".
- local row
- local column
- for (( row = ROW; row > -ROW; row-- ))
- do
- for (( column = 0; column < COL; column++ ))
- do
- if [ "$row" -ge 0 ]
- then
- let "t1 = $column - $row"
- let "t2 = $column"
- else
- let "t1 = $column"
- let "t2 = $column + $row"
- fi
- filter $t1 $t2 # 将负的数组下标过滤出来
- done
- echo; echo
- done
- }
- #下面利用上述函数创建二维数组,逐行和旋转45°打印数组
- load_alpha # 加载数组
- print_alpha # 打印数组
- rotate # 逆时针旋转45°打印
三、总结
(1)别名、列表及数组这三个知识点是相对独立的,可分开理解。
(2)数组是重点,会使用数组字符串的操作,以及利用数组实现堆栈和二维数组等数据结构。
更多推荐
所有评论(0)