www.9778.com(4)shell脚本编程进阶之数组、字符串切片

数组就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,然后用编号区分他们的变量的集合,这个名字称为数组名,编号称为下标。组成数组的各个变量称为数组的元素。数组是在程序设计中,为了处理方便,
把具有相同类型的若干变量按有序的形式组织起来的一种形式。

(一)数组定义

  • 数组:存储多个元素的连续的内存空间,相当于多个变量的集合
  • 数组名和索引
  • 索引:编号从0 开始,属于数值索引
  • 注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,
    bash4.0版本之后开始支持
  • bash 的数组支持稀疏格式(索引不连续)
  • 声明数组:
    declare -a ARRAY_NAME
    declare -A ARRAY_NAME: 关联数组
    注意:两者不可相互转换
  • (1)数组赋值
    • 一次只赋值一个元素;
      ARRAY_NAME[INDEX]=VALUE
      weekdays[0]=”Sunday”
      weekdays[4]=”Thursday”
    • (一次赋值全部元素:
      ARRAY_NAME=(“VAL1” “VAL2” “VAL3” …)
    • 只赋值特定元素:
      ARRAY_NAME=([0]=”VAL1″ [3]=”VAL2″ …)
    • 交互式数组值对赋值
      read -a ARRAY

前言

之前写过一篇关于shell脚本流程控制总结,这次继续写关于shell脚本的问题。本篇文章主要包含shell脚本中的函数以及数组的用法介绍。同时也涵盖了一些字符串处理以及shell脚本比较使用的小工具的介绍。

一、数组的表示方式

(二)引用数组

  • 引用数组元素:${ARRAY_NAME[INDEX]}注意:省略[INDEX]
    表示引用下标为0 的元素
  • 数组的长度( 数组中元素的个数):
    ${#ARRAY_NAME[*]}
    ${#ARRAY_NAME[@]}

示例:生成10 个随机数保存于数组中,并找出其最大值和最小值
#!/bin/bash
declare -a rand
declare -i max=0
declare –i min=32767
for i in {0..9}; do
rand[$i]=$RANDOM
echo ${rand[$i]}
[ ${rand[$i]} -gt $max ]&& max=${rand[$i]}
[ ${rand[$i]} -lt $min ]&& min=${rand[$i]}
done
echo “Max: $max Min:$min”

编写脚本,定义一个数组,数组中的元素是/var/log 目录下所有以
.log 结尾的文件;要统计其下标为偶数的文件中的行数之和
#!/bin/bash
declare -a files
files=(/var/log/www.9778.com(4)shell脚本编程进阶之数组、字符串切片。.log)
declare -i lines=0
for i in $(seq 0 $[${#files[
]}-1]); do
if [ $[$i%2] -eq 0 ];then
let lines+=$(wc -l ${files[$i]} | cut -d’ ‘ -f1)
fi
done
echo “Lines: $lines.”

  • (3)数组数据处理
    • 引用数组中的元素:
      所有元素:${ARRAY[@]}, ${ARRAY[*]}
    • 数组切片:${ARRAY[@]:offset:number}
      • offset: 要跳过的元素个数
      • number: 要取出的元素个数
      • 取偏移量之后的所有元素
        ${ARRAY[@]:offset}
    • 向数组中追加元素:
      ARRAY[${#ARRAY[*]}]
    • 删除数组中的某元素:导致稀疏格式
      unset ARRAY[INDEX]
    • 删除整个数组:unset ARRAY
    • 关联数组:
      declare -A ARRAY_NAME 注意:必须先声明,再调用
      www.9778.com,ARRAY_NAME=([idx_name1]=’val1′ [idx_name2]=’val2‘…)

函数

函数function是由若干条shell命令组成的语句块,实现代码重用和模块话编程。
它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分。
函数shell程序比较相似,区别在于:
shell程序在shell中运行
而shell函数在当前shell中运行。因此在当前shell中,函数可以对shell中变量进行修改。

1、下标数组

(三)字符串切片

定义函数

函数由两部分组成:函数名和函数体

语法一: 
function f_name { 
...函数体... 
} 

语法二: 
function f_name () { 
...函数体... 
} 
#语法三的写法相对简单,并且系统中的函数一般也使用第三种写法,所以简易使用第三中写法。
语法三: 
f_name (){ 
...函数体... 
}

下标必须为整数,格式:数组名[下标],下标默认从0开始。
shell支持稀疏数组,下标整数不需要连续。
声明方式:declare -a 数组名

(1)字符串处理切片
  • ${#var}: 返回字符串变量var 的长度
  • ${var:offset}: 返回 字符串变量var
    中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0
    ${#var}-1之间(bash4.2 后,允许为负值)
  • ${var:offset:number} :返回 字符串变量var
    中从第offset个字符后(不包括第offset个字符)的字符开始
    ,长度为number 的部分
  • ${var: -length}:取字符串的最右侧几个字符注意:冒号后必须有一空白字符
  • ${var:offset:-length}:从最左侧跳过offset
    字符,一直向右取到距离最右侧lengh 个字符之前的内容
  • ${var: -length:-offset}:先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容

函数返回值

函数有两种返回值:

  1. 函数的执行结果返回值:
    (1)使用echo等命令进行输出
    (2)函数中调用命令的输出结果
  2. 函数的退出状态码
    (1)默认取决于函数中执行的最后一条命令的退出状态码
    (2)自定义退出状态码,其格式为,:
    return 从函数中返回,用最后状态命令决定返回值
    return 0 无错误返回
    return 1-255有错误返回

2、关联数组

(2)字符串处理
  • (1)基于模式取子串

  • ${var#*word}:其中word 可以是指定的任意字符

  • 功能:自左而右,查找var 变量所存储的字符串中,第一次出现的word,
    删除字符串开头至第一次出现word 字符之间的所有字符

  • ${var##*word}:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word
    指定的字符之间的所有内容

     示例:
     file="var/log/messages“
     ${file#*/}: log/messages
     ${file##*/}: messages
    
  • ${var%word*}:其中word 可以是指定的任意字符;

  • 功能:自右而左,查找var 变量所存储的字符串中,第一次出现的word,
    删除字符串最后一个字符向左至第一次出现word 字符之间的所有字符;
    file=”/var/log/messages”
    ${file%/*}: /var/log

  • ${var%%word*}:同上,只不过删除字符串最右侧的字符向左至最后一次出现word
    字符之间的所有字符;
    示例:
    url=http://www.magedu.com:80
    ${url##:} 80
    ${url%%:
    } http

函数的使用

  1. 可以在交互式环境下定义函数
  2. 可将函数放在脚本文件中作为他的一部分
  3. 可以单独写在一个文件中功能模块化,使用的时候单独调用

关联数组可以使用任意的字符串作为下标(不必是整数)来访问数组元素。bash4.0开始支持关联数组。
格式:数组名[任意字符串]
声明方式:declare -A 关联数组
另外,shell只支持一维数组,不支持多维数组。

(2)字符串查找替换
  • ${var/pattern/substr}:查找var 所表示的字符串中,第一次被pattern
    所匹配到的字符串,以substr替换之

  • ${var//pattern/substr}:
    查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之

  • ${var/#pattern/substr}:查找var
    所表示的字符串中,行首被pattern 所匹配到的字符串,以substr替换之

  • ${var/%pattern/substr}:查找var
    所表示的字符串中,行尾被pattern所匹配到的字符串,以substr 替换之

  • ${var/pattern}:查找var所表示的字符串中,删除第一次被pattern所匹配到的字符串

    ${var//pattern} :所有
    ${var/#pattern} :行首
    ${var/%pattern} :行尾
    
  • 字符大小写转换

  • ${var^^}:把var 中的所有小写字母转换为大写

  • ${var,,}:把var中的所有大写字母转换为小写

  • 变量赋值

  • ${var:-value}:如果var
    为空或未设置,那么返回value;否则返回var 的值,可省略:

  • ${var:+value}:如果var不空,则返回value ,否则返回空值

  • ${var:=value} :如果var
    为空或未设置,那么返回value,并将value
    赋值给var;否则返回var的值

  • ${var:?error_info}:如果var为空或未设置,那么在当前终端打error_info
    ;否则返回var 的值

  • 为脚本程序使用配置文件, 实现变量赋值

  • (1) 定义文本文件,每行定义“name=value”

  • (2) 在脚本中source此文件即可

交互式环境使用函数

交互式环境下别名的优先级高于函数,如果函数的名字与别名相同,那么优先运行别名。但是一般函数只在脚本中使用,而脚本中别名不生效,所以不用考虑这个问题。
declear -f 查看所有定义过的函数。
交互式环境下函数会一直保留到用户从系统中退出,或者unset funcname
清除。
调用:函数只有被调用才会执行
调用:给定函数名
函数名出现的地方,会被自动替换为函数代码。
函数的声明周期:被调用时创建,返回时终止
函数的定义会影响当前shell环境,使用local
声明函数定义的内容只在函数内部生效

当函数要定义一个数字时使用declare -i
声明要定义的函数是一个数字,声明的同时也会附带声明函数的本地效果,既只在函数内部生效。加参数-g再次声明为全局变量:declare
-ig

[root@CentOS6 ~]#name=wang
[root@CentOS6 ~]#func1 () { name=mage; echo $name ; }
[root@CentOS6 ~]#func1
mage
[root@CentOS6 ~]#echo $name
mage
[root@CentOS6 ~]#name=wang
[root@CentOS6 ~]#func1 () { local name=mage; echo $name ; }
[root@CentOS6 ~]#echo $name
wang

二、数组的赋值

(三)高级变量用法-有类型变量

在脚本中定义及使用函数

函数在使用前必须定义,因此应将函数定义放在脚本开始本分,直至shell首次发现它后才能使用。
调用函数仅仅使用其函数名即可。

www.9778.com 1

(1)declare命令

Shell 变量一般是无类型的,但是bash Shell 提供了declaretypeset
declare [ 选项] 变量名
-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示此脚本前定义过的所有函数名及其内容
-F 仅显示此脚本前定义过的所有函数名
-x 声明或显示环境变量和函数
-l 声明变量为小写字母
declare –l var=UPPER
-u 母 声明变量为大写字母
declare –u var=lower

函数变量

变量作用域:
环境变量:当前shell和子shell有效
本地变量:只在当前shell进程有效,为执行脚本会启动
专用子shell进程;因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数
局部变量:函数的生命周期;函数结束时变量被自动销毁
注意:如果函数中有局部变量,如果其名称同本地变量,使 用局部变量
在函数中定义局部变量的方法 local NAME=VALUE

[root@CentOS6 bin]#vim testfunc.sh 
#!/bin/bash
func1 () {
    echo "func1 is running"     #定义函数执行echo命令
    local funcvar="i am func1"  #函数内定义本地变量
    echo $funcvar               #函数内显示本地变量
}
echo func1 will start...
func1                           #调用函数
echo func1 is finished
echo "funcvar is  $funcvar"     #函数外显示变量
"testfunc.sh" 20L, 500C written                           
[root@CentOS6 bin]#testfunc.sh 
func1 will start...
func1 is running
i am func1                      #函数内显示函数本地变量
func1 is finished
funcvar is                      #函数外显示变量为空
#函数中使用变量一般使用local关键字定义本地变量,否则容易影响脚本中的变量。

三、数组的访问

(2)eval 命令
  • 定义:eval
    命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
    [root@server ~]# CMD=whoami
    [root@server ~]# echo $CMD
    whoami
    [root@server ~]# eval $CMD
    root
    [root@server ~]# n=10
    [root@server ~]# echo {0..$n}
    {0..10}
    [root@server ~]# eval echo {0..$n}
    0 1 2 3 4 5 6 7 8 9 10

使用函数文件

可以将经常使用的函数存入函数文件,然后将函数文件载入shell,这样一些常用的函数就不用每次用到都要重新去写了。
函数文件的文件名可任意选取,但最后是与相关的任务有联系,例如:functions.main
一旦函数文件载入shell,就可以在命令行或者脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包含已经载入shell的所有函数。
若要改动函数,首先用unset命令将函数从shll中删除。改动完毕后,在重新载入函数文件。

通过操作语法来实现对数组元素的访问。

(3)间接变量引用
  • 如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
  • variable1 的值是variable2,而variable2 又是变量名,variable2
    的值为value ,间接变量引用是指通过variable1获得变量值value
    的行为
    variable1=variable2
    variable2=value
  • bash Shell 提供了两种格式实现间接变量引用
    eval tempvar=$$variable1
    tempvar=${!variable1}
    示例:
    [root@server ~]# N=NAME
    [root@server ~]# NAME=wangnan
    [root@server ~]# N1=${!N}
    [root@server ~]# echo $N1
    wangnan
    [root@server ~]# eval N2=$$N
    [root@server ~]# echo $N2
    wangxnan

创建函数文件:

函数文件示例:

[root@CentOS6 bin]#cat functions.main 
#!/bin/bash
# Filename  : functions.main
#---------------+--------------------------------------+
findit () {
    if [ $# -lt 1 ] ;then
        echo "Usage:findit file"
        return 1
    fi
    find / -name $1 -print
}

语法格式有以下几种:

载入函数文件:

函数文件创建好之后,要将他载入shell中
定位函数文件,并载入shell的格式为:
点 空格 文件名:. filename
或 source 空格问价名:source filename
文件名要带正确路径

[root@CentOS6 ~]#. /etc/rc.d/init.d/functions #系统自带的函数
[root@CentOS6 ~]#action "success"
success                                              [  OK  ]

数组的长度:

删除shell函数

现在对函数做一些改动后,需要先删除函数,使其对shell不可用,
使用unset命令完成删除函数
命令格式为:
unset function_name

[root@CentOS6 bin]#unset findit
[root@CentOS6 bin]#findit
-bash: findit: command not found

${#ARRAY[*]}:显示元素个数;
${#ARRAY[@]}:显示元素个数;
${#ARRAY[#]}:第#个元素的字符个数;
${#ARRAY}:第0个元素的字符个数;

环境函数

当前进程导入的函数不能传给子进程
声明函数为环境函数使子进程也可以使用
声明:export –f function_name
查看:export -f 或 declare -xf

数组的元素:

函数参数

函数可以接受参数:
传递参数给函数:调用函数时在函数名后面以空白分隔给定参数列表即可:例如“testfunc
arg1 arg2 …”
在函数体中当中,可使用$1, $2, …调用这些参数;还 可以使用$@, $*,
$#等特殊变量

[root@CentOS6 bin]#vim testfunc2.sh 
#!/bin/bash
func1 () {
        echo "func1 1st var is $1"
        echo "func1 2st var is $2"
        echo "func1 3st var is $3"
        echo "the func1var is $*"
}
func1 func{$1,$2,$3}
echo "the scriptvar is $*"
[root@CentOS6 bin]#testfunc2.sh x y z
func1 1st var is funcx
func1 2st var is funcy
func1 3st var is funcz
the func1var is funcx funcy funcz
the scriptvar is x y z

${ARRAY[*]}:显示所有元素内容;
${ARRAY[@]}:显示所有元素内容;
${ARRAY[#]}:显示第#个元素;
${ARRAY}:显示第0个元素;

函数递归示例

函数递归:
函数直接或间接调用自身
注意递归层数
一般循环可以解决的问题不用递归
递归实例:
阶乘是基斯顿·卡曼于 1808 年发明的运算符号,是数学术语
一个正整数的阶乘(factorial)是所有小于及等于该数的正整
数的积,并且有0的阶乘为1,自然数n的阶乘写作n!
n!=1×2×3×…×n
阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n
n!=n(n-1)(n-2)…1
n(n-1)! = n(n-1)(n-2)!

[root@CentOS6 bin]#vim n!.sh 
#!/bin/bash
fact () {
    if [ $1 -eq 1 -o $1 -eq 0 ] ; then
        echo 1      #1和0的阶乘都是1
    else echo $[$1*`fact $[$1-1]`]
    fi
      }
fact $1

数组的键值:

fork炸弹

fork炸弹是一种恶意程序,它的内部是一个不断在fork进程
的无限循环,实质是一个简单的递归程序。由于程序是递归
的,如果没有任何限制,这会导致这个简单的程序迅速耗尽
系统里面的所有资源
函数实现
:(){ :|:& };:
bomb() { bomb | bomb & }; bomb
脚本实现
cat Bomb.sh
#!/bin/bash
./$0|./$0&

$[!ARRAY[*]}:显示所有的键值;
$[!ARRAY[@]}:显示所有的键值。

数组

数组的作用以及意义与变量类似
变量:储存单个元素的内存空间。
数组:存储多个元素的连续的内存空间,相当于多个变量的集合
数组名和索引:
索引:编号从0开始,属于数值索引
注意:数组索引支持使用自定义格式,即为关联所索引,bash4.0版本之后开始支持
bash的数组支持稀疏格式(索引不连续)

实例:写一个脚本,生成10个随机数,保存至数组中,而后显示数组下标为偶数的元素:

声明数组:

declare -a ARRAY_NAME
declare -A ARRAY_NAME: 关联数组
注意:关联数组和一般数组之间不可相互转换

www.9778.com 2

数组元素的赋值:

  1. 一次只赋值一个元素
    ARRAY_NAME[INDEX]=VALUE
    weekdays[0]=”Sunday”
    weekdays[4]=”Thursday”
    #双引号可以不加,但是如果元素中含有空格需要双引号
  2. 一次赋值全部元素
    ARRAY_NAME=(“VAL1” “VAL2” “VAL3” …)

    [root@CentOS6 ~]#title=(boss ceo coo cto opt)
    [root@CentOS6 ~]#echo ${title[*]}
    boss ceo coo cto opt
    

    数组的复制支持列表格式和seq命令

  3. 只赋值特定元素 (稀疏格式)
    ARRAY_NAME=([0]=”VAL1″ [3]=”VAL2″ …)

  4. 交互式数组值对赋值
    read -a ARRAY
    显示所有数组:declare -a

四、从数组中挑选元素

引用数组

引用数组元素:
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下标为0的元素
引用数组所有元素:
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
数组的长度(数组中元素的个数):
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
数组元素个数减一等于最末端数组元素下标
遍历数组:

[root@CentOS6 ~]#for i in `seq 0 $[${#title[*]}-1]` ;do echo title[$i]=${title[$i]}; done
title[0]=boss
title[1]=ceo
title[2]=coo
title[3]=cto
title[4]=opt

删除数组中的某元素:导致稀疏格式
unset ARRAY[INDEX]
删除整个数组:
unset ARRAY

如果想要从数组中取出某几个元素时,使用下标逐个查找比较麻烦,可以使用数组的偏移元素功能来简化操作。

数组处理

语法格式:

引用数组中的元素

数组切片: ${ARRAY[@]:offset:number}
offset:要跳过的元素个数
number:要取出的元素个数
取偏移量之后的所有元素:
${ARRAU[@]:offset}

${ARRAY[@]:offset:number}
offset:偏移元素个数;
number:取出的元素个数;

向元素中追加元素

元素个数减一,是数组中最末端的元素的下标,所以在确保数组不是稀疏格式的前提下,要想数组中追加的元素的下标等于当前数组的数量。
ARRY[${#ARRY[*]}]=vale

实例:数组off_array中有6个元素,假设我们想要取3月到5月这三个值:

关联数组

declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]=’val1′ [idx_name2]=’val2‘…)
注意:关联数组必须先声明再调用

www.9778.com 3

练习

  1. 生成十个随机数保存在数组中,并找出其最大值和最小值

    [root@CentOS6 bin]#vim max.sh 
    #!/bin/bash
    declare -i min max          #声明max min都是数值
    declare -a digit            #声明数组
    for ((i=0;i<10;i++));do     #引入变量I初始值0,循环十次,每次循环以后自增1
    digit[$i]=$RANDOM       #取随机数赋值给数组元素
    [ $i -eq 0 ] && max=${digit[$i]} && min=${digit[$i]} && continue
    #每次循环都给最大值和最小值重新赋值,第一次循环最大最小值都是digit[i]并且continue跳过本次循环
    [ ${digit[$i]} -gt $max ] && max=${digit[$i]}
    #如果digit[$i]大于当前最大值$max时,就将digit[$i]重新付给max
    [ ${digit[$i]} -lt $min ] && min=${digit[$i]}
    #如果digit[$i]小于当前最小值$max时,就将digit[$i]重新付给min
    done
    echo ALL digit are ${digit[*]}
    echo Max is $max
    echo Min is $min
    [root@CentOS6 bin]#max.sh 
    ALL digit are 22019 3896 15981 5024 6535 4256 14632 31882 395 1400
    Max is 31882
    Min is 395
    
  2. 编写脚本,定义一个数组,数组的元素是/var/log目录下所有以.log结尾的文件;统计其下标为偶数的文件中的行数之和

    [root@CentOS6 bin]#vim linesum.sh 
    #!/bin/bash
    declare -a logfiles=(/var/log/*.log)    #定义数组
    #echo All logfile are ${logfiles[@]}
    i=0
    linesum=0
    filelines=0
    while [ $i -lt ${#logfiles[@]} ] ; do   #循环次数为数组元素个数
    if [ $[$i%2] -eq 0 ] ;then      #判断数组下标为偶数通过条件判断
        filelines=`cat /${logfiles[$i]} | wc -l`    #将下标为偶数的文件行数赋值给变量filelines
        let linesum+=$filelines     #加总
        echo ${logfiles[$i]} filelines is $filelines
    fi
    let i++     #变量i也就是数组元素下标自增
    done
    echo linesum is $linesum                                   
    [root@CentOS6 bin]#linesum.sh 
    /var/log/anaconda.ifcfg.log filelines is 219
    ...         #省略
    /var/log/Xorg.9.log filelines is 309
    linesum is 4194
    

五、数组复制

字符串切片

${#var}:返回字符串变量var的长度
${var:offset}:返回字符串变量var中从第offset个字符后(不包括
第offset个字符)的字符开始,到最后的部分,offset的取值在0 到 ${#var}-1
之间(bash4.2后,允许为负值)
${var:offset:number}:返回字符串变量var中从第offset个字符后
(不包括第offset个字符)的字符开始,长度为number的部分
${var: -length}:取字符串的最右侧几个字符 注意:冒号后必须有一空白字符
${var:offset:-length}:从最左侧跳过offset字符,一直向右取到
距离最右侧lengh个字符之前的内容
${var: -length:-offset}:先从最右侧向左取到length个字符开始
,再向右取到距离最右侧offset个字符之间的内容
注意:-length前空格

$@:每个参数是一个独立的串,建议使用;
$*:所有元素当做一个串。

基于模式取子串

${var#*word}:其中word可以是指定的任意字符
功能:自左而右,查找var变量所存储的字符串中,第一 次出现的word,
删除字符串开头至第一次出现word字符之间的 所有字符
${var##*word}:同上,贪婪模式,不同的是,删除的
是字符串开头至最后一次由word指定的字符之间的所有内容
示例:

[root@CentOS6]#file=var/log/messages
[root@CentOS6]#echo ${file#*/}
log/messages
[root@CentOS6]#echo ${file##*/}
messages

${var%word*}:其中word可以是指定的任意字符;
功能:自右而左,查找var变量所存储的字符串中,第一 次出现的word,
删除字符串最后一个字符向左至第一次出现 word字符之间的所有字符;
file=”/var/log/messages”
${file%/*}: /var/log
${var%%word*}:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符;
示例:

[root@CentOS6 ~]#url=http://www.badu.com:80
[root@CentOS6 ~]#echo ${url##*:}
80
[root@CentOS6 ~]#echo ${url%%:*}        #:*顺序有变化
http

实例:复制一个数组中下标为偶数的元素至新数组中:

查找替换

${var/pattern/substr}:查找var所表示的字符串中,第
一次被pattern所匹配到的字符串,以substr替换之
${var//pattern/substr}: 查找var所表示的字符串中,
所有能被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}:查找var所表示的字符串中,
行首被pattern所匹配到的字符串,以substr替换之
${var/%pattern/substr}:查找var所表示的字符串中,
行尾被pattern所匹配到的字符串,以substr替换之

www.9778.com 4

查找删除

${var/pattern}:删除var所表示的字符串中第一次被
pattern所匹配到的字符串
${var//pattern}:删除var所表示的字符串中所有被 pattern所匹配到的字符串
${var/#pattern}:删除var所表示的字符串中所有以
pattern为行首所匹配到的字符串
${var/%pattern}:删除var所表示的字符串中所有以
pattern为行尾所匹配到的字符串

六、从数组中删除元素

大小写转换

${var^^}:把var中的所有小写字母转换为大写
${var,,}:把var中的所有大写字母转换为小写

格式:unset 数组名[下标]

高级变量用法-有类型变量

shell变量一般是无类型的,但是bash
shell提供了declare和typest两个命令用于指定变量的类型,两个命令是等价的
declare [选项] 变量名
-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示已定义的所有函数名及其内容
-F 仅显示已定义的所有函数名
-x 声明或显示环境变量和函数
-l 声明变量为小写字母 declare –l var=UPPER
-u 声明变量为大写字母 declare –u var=lower

www.9778.com 5

eval命令

eval命令将会首先扫描命令行进行所有的置换,让你后在执行该敏玲。该命令适用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描
示例:

[root@CentOS6 ~]#CMD=whoami
[root@CentOS6 ~]#echo $CMD
whoami
[root@CentOS6 ~]#eval $CMD
root
[root@CentOS6 ~]#n=10
[root@CentOS6 ~]#echo {0..$n}
{0..10}
[root@CentOS6 ~]#eval echo {0..$n}
0 1 2 3 4 5 6 7 8 9 10

七、综合实例

间接变量引用

如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量应用。
variable1的值是variable2,而variable2又是变量名,
variable2的值为value,间接变量引用是指通过variable1获
得变量值value的行为
variable1=variable2
variable2=value
bash shell提供了两种格式实现间接变量引用
eval tempvar=$$variable1
tempvar=${!variable1}

生成10个随机数,并对这10个随机数进行排序。

创建临时文件

mktemp命令:创建并显示临时文件,可避免冲突
mktemp [OPTION]… [TEMPLATE]
TEMPLATE: filename.XXX
X至少要出现三个

[root@CentOS6 app]#mktemp /app/tmpfile.XXX
/app/tmpfile.8Tw    #文件后缀必须是大写X有多少个X就会生成多少个随机字符
#赋值给变量直接引用
[root@CentOS6 app]#tmpfile=`mktemp /app/tmpfile.XXX`
[root@CentOS6 app]#echo $tmpfile
/app/tmpfile.2AO
将指定目录赋值给变量直接引用
[root@CentOS6 app]#dir=/app
[root@CentOS6 ~]#mktemp  -p $dir testfile.XXX
/app/testfile.wzQ

OPTION:
-d: 创建临时目录
-p DIR或–tmpdir=DIR:指明临时文件所存放目录位置
示例:
mktemp /tmp/test.XXX
tmpdir=`mktemp –d /tmp/testdir.XXX`
mktemp –tmpdir=/testdir test.XXXXXX

www.9778.com 6

安装复制文件

install命令:
install [OPTION]… [-T] SOURCE DEST 单文件
install [OPTION]… SOURCE… DIRECTORY
install [OPTION]… -t DIRECTORY SOURCE…
install [OPTION]… -d DIRECTORY…创建空目录
选项:
-m MODE,指定权限默认755
-o OWNER 指定所有者
-g GROUP 指定所属组
示例:
install -m 700 -o wang -g admins srcfile desfile
install –m 755 –d /testdir/installdir
若有疑问以及错误指正请留言吧。