shell脚本进阶

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell脚本进阶相关的知识,希望对你有一定的参考价值。

for语句
for 变量名 in 取值列表; do 
    命令 
done

示例:

#!/bin/bash 
for i in 1..3; do 
echo $i 
done 
#bash test.sh 
1 
2 
3

类似c语言风格,常用于计数,打印数字序列

#!/bin/bash 
for ((i=1;i<=5;i++)); do # 也可以i--   
echo $i 
done

while语句

while 条件表达式; do 
    命令 
done

实例:

#!/bin/bash 
N=0 
while [ $N -lt 5 ]; do
            let N++ 
            echo $N 
done 
#bash test.sh 
1 
2 
3 
4

当条件表达式为false时,终止循环
实例2:条件表达式为ture,将会产生死循环

#!/bin/bash 
while [ 1 -eq 1 ]; do 
    echo "yes" 
done

break和contime语句

break是终止循环
continue跳出当前循环
示例1:在死循环中,满足条件终止循环

#!/bin/bash 
N=0 
while true; do 
        let N++ 
        if [ $N -eq 5 ]; then 
            break 
        fi 
        echo $N 
    done 
    #bash test.sh 
    1 
    2 
    3 
    4

说明continue用法

#!/bin/bash 
N=0 
while [ $N -lt 5 ]; do 
    let N++ 
    if [ $N -eq 3 ]; then 
        continue 
    fi 
    echo $N done 
#bash test.sh 
1 
2 
4

case语句

case 模式名 in 
    模式1) 
        命令 
        ;; 
    模式2) 
        命令 
        ;; 
        *) 
        不符合以上模式执行的命令 
esac

示例:根据位置参数匹配不同的模式

#!/bin/bash 
case $1 in 
    start)
        echo "start."
        ;; 
    stop) 
        echo "stop."
        ;; 
    restart) 
        echo "restart." 
        ;; 
    *) 
    echo "Usage: $0 start|stop|restart" 
esac 
#bash test.sh 
Usage: test.sh start|stop|restart 
#bash test.sh start 
start. 
#bash test.sh stop 
stop. 
#bash test.sh restart 
restart.

select语句

select 变量 in 选项 1 选项2; do
    break
done

实例:

#!/bin/bash 
select mysql_version in 5.1 5.6; do 
        echo $mysql_version 
done
#bash test.sh 
1) 5.1 
2) 5.6 
#? 1 
5.1 
#? 2 
5.6

PS3="Select a number: " 可以定义select输入符

函数

格式: function关键字可写,也可不写

func()  
    command 

实例:

#!/bin/bash 
func()  
    echo "This is a function." 
 
func  #调用
#bash test.sh 
This is a function.

实例2:函数返回值

#!/bin/bash 
func()  
    VAR=$((1+1)) 
    return $VAR  #return在函数中定义状态返回值,返回并终止函数,但返回的只能是0-255的数字,类似于exit
    echo "This is a function." 
 
func 
echo $? 
#bash test.sh
2

函数也支持递归调用,就是自己调用自己
列如:

#!/bin/bash 
test()  
    echo $1 
    sleep 1 
    test hello 
 
test

会一直调用打印hello ,形成了闭环
fork×××及时函数递归调用

:() :|:& ;: 或 .().|.&;.

:() 定义一个函数,函数名是冒号。
: 调用自身函数
| 管道符
: 再一次递归调用自身函数
:|: 表示每次调用函数":"的时候就会生成两份拷贝。
& 放到后台
; 分号是继续执行下一个命令,可以理解为换行。
: 最后一个冒号是调用函数。
因此不断生成新进程,直到系统资源崩溃。

数组

变量:存储单个元素的内存空间
数组:存储多个元素的连续的内存空间,相当于多个变量的集合
数组是相同类型的元素按一定顺序排列的集合。
顺序编号是数组的索引或者下标。
下标可以是任意的字符
自定义的下标为关联数组,必须先声明在使用,和普通数组之间不可以转换
下标不连续为稀疏数组
格式:

array=(元素1 元素2 元素3 ...)
用小括号初始化数组,元素之间用空格分隔。
定义方法1:初始化数组
array=(a b c)
定义方法2:新建数组并添加元素
array[下标]=元素
定义方法3:将命令输出作为数组元素
array=($(command))
交互式数组值对赋值
read -a array

数组操作:

获取所有元素: 
#echo $array[*] # *和@ 都是代表所有元素 
a b c 
获取元素下标: 
#echo $!a[@] 
0 1 2 
获取数组长度: 
#echo $#array[*] 
3 
获取第一个元素: 
#echo $array[0] 
a 
获取第二个元素: 
#echo $array[1] 
b 
获取第三个元素: 
#echo $array[2] 
c 
添加元素: 
#array[3]=d 
#echo $array[*] 
a b c d 
添加多个元素: 
#array+=(e f g) 
#echo $array[*] 
a b c d e f g 
将数组的元素个数作为数组新元素的下标,新元素下标为原顺序编号个数
#array[$#array[@]]=h
删除第一个元素: 
#unset array[0] # 删除会保留元素下标 
#echo $array[*] 
b c d e f g 
删除数组: 
#unset array
关联数组:必须声明才能使用
#student[a]=aaa
#student[b]=bbb
#student[c]=ccc
#echo $studen[a]
ccc
#echo $student[b]
ccc
#echo $student[c]
ccc
#unset student  #删除标准数组
#declare -A studeny #声明
#student[a]=aaa
#student[b]=bbb
#student[c]=ccc
#echo $studen[a]
aaa
#echo $student[b]
bbb
#echo $student[c]
ccc

信号捕捉

信号(Signal):信号是在软件层次上对中断机制的一种模拟,通过给一个进程发送信号,执行相应的处理函数。
进程可以通过三种方式来响应一个信号:
1)忽略信号,即对信号不做任何处理,其中有两个信号不能忽略:SIGKILL及SIGSTOP。
2)捕捉信号。
3)执行缺省操作,Linux对每种信号都规定了默认操作

trap命令

trap命令定义shell脚本在运行时根据接收的信号做相应的处理。
命令格式:trap [-lp] [[arg] signal_spec ...]
-l # 打印编号1-64编号信号名称
arg # 捕获信号后执行的命令或者函数
signal_spec # 信号名或编号
一般捕捉信号后,做以下几个动作:
1)清除临时文件
2)忽略该信号
3)询问用户是否终止脚本执行
示例1:按CTRL+C不退出循环

#!/bin/bash 
trap "" 2 # 不指定arg就不做任何操作,后面也可以写多个信号,以空格分隔 
for i in 1..10; do 
    echo $i 
    sleep 1 
done 
# bash a.sh 
1 
2 
3 
^C
4 
5 
6 
^C
7 
8
^C
9 
10

字符串切片:

$#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个字符之
间的内容

字符串处理:
基于模式取子串

$var#*word:其中word可以是指定的任意字符
功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字
符串(含)之间的所有字符
$var##*word:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所
有内容
$var%word*:其中word可以是指定的任意字符
功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一
次出现word字符串(含)之间的所有字符
file="/var/log/messages"
$file%/*: /var/log
$var%%word*:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符

Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令?于指定变量的类型,两个命令是等价的
declare [选项] 变量名

-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示已定义的所有函数名及其内容
-F 仅显示已定义的所有函数名
-x 声明或显示环境变量和函数
-l 声明变量为小写字母 declare –l var=UPPER
-u 声明变量为大写字母 declare –u var=lower

eval命令:
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的
变量.该命令对变量进行两次扫描
间接变量引用
如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用

variable1的值是variable2,而variable2又是变量名,variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为
variable1=variable2
variable2=value

expect命令:
expect 语法:expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
选项

-c:从命令行执行expect脚本,默认expect是交互地执行的
示例:expect -c ‘expect "\n" send "pressed enter\n"
-d:可以输出输出调试信息
示例:expect -d ssh.exp
expect中相关命令
spawn 启动新的进程
send 用于向进程发送字符串
expect 从进程接收字符串
interact 允许用户交互
exp_continue 继续执行下面匹配

实例:非交互式登录远程主机

 #!/usr/bin/expect
 set ip 172.16.11.3
 set user root
 set password 123123
 set timeout 10
 spawn ssh [email protected]$ip
 expect                                                          
 "yes/no"  send "yes\n";exp_continue 
 "password"  send "$password\n" 
 
 interact

以上是关于shell脚本进阶的主要内容,如果未能解决你的问题,请参考以下文章

SHELL脚本编程进阶

Shell脚本之进阶

代码片段:Shell脚本实现重复执行和多进程

shell脚本进阶

shell 脚本 片段

Linux shell脚本进阶使用