23
SHELL 脚脚脚脚 林林林 2005-3-12 [email protected]

SHELL 脚本编程

Embed Size (px)

DESCRIPTION

SHELL 脚本编程. 林怀东 2005-3-12 [email protected]. Outline. Shell 脚本简介 常用 shell 命令 Shell 常用变量 流程控制 Shell 函数. shell 脚本介绍. 一个 shell 脚本可以包含一个或多个 shell 命令,可用来自动完成通常在命令行上执行的重复循环或者复杂的工作,节省大量时间,且功能强大 shell 脚本主要内容 脚本按行解释执行,每一行可 以是命令、注解、或是流程控制指令等 - PowerPoint PPT Presentation

Citation preview

Page 1: SHELL 脚本编程

SHELL脚本编程

林怀东2005-3-12

[email protected]

Page 2: SHELL 脚本编程

Outline

Shell 脚本简介 常用 shell 命令 Shell 常用变量 流程控制 Shell 函数

Page 3: SHELL 脚本编程

shell 脚本介绍一个 shell 脚本可以包含一个或多个 shell 命令,可用

来自动完成通常在命令行上执行的重复循环或者复杂的工作,节省大量时间,且功能强大

shell 脚本主要内容 脚本按行解释执行,每一行可 以是命令、注解、或是流程控制指令

等 脚本第一行以 #! 开始,后面加所使用的 shell (需指明整个路径名

称) ( 如:以 #!/bin/sh 指定使用 Bourne Shell ) 在脚本中执行一个命令的方法和在命令行中相同,可以前台或后台

执行,也可设定一些环境变量 注释, # 后面的同一行文字为注释,解释器对此不予解释 脚本的流程控制近似于一般高级语言,这使得脚本的功能比 DOS 的

批处理文件功能更加强大

Page 4: SHELL 脚本编程

常用 shell 命令 文件及文件属性操作

ls 、 cp 、 mv 、 rm ln 、 ln –s 、 chmod 、 chown 、 chgrp

输入输出操作 echo 、 cat >> 、 > 、 << 、 | 标准输入 0 、标准输出 1 、 标准错误输出 2

目录操作 cd 、 pwd 、 ls dir mkdir 、 cp 、 mv 、 rmdir 、 rm -r

文本过滤 Head 、 tail 、 grep 、 sort 、 uniq sed 、 awk

其他 find 、 expr

获取信息: man

Page 5: SHELL 脚本编程

正则表达式—— sed 与 awk 的基础

正则表达式是一些特殊或不很特殊的字符串模式的集合。 字符集包括:普通字符集和元字符集(通配符)

普通字符集:大小写字母、数字、空格、下划线 ^ 行首 $ 行尾 * 一个单字符后紧跟 * ,匹配 0 个或多个此单字符 [ ] 匹配 [ ] 内字符,可以是一个单字符,也可以是字符序列。

可以使用” -“ 来表示 [ ] 内范围,如 [1-5] 等价于 [1,2,3,4,5] 。 \ 屏蔽一个元字符的特殊含义,如 \$ 表示字符 $ ,而不表示匹配行尾。 . 匹配任意单字符

几个常见的例子: 显示可执行的文件: ls –l | grep …x...x..x 只显示文件夹: ls –l | grep ^d 匹配所有的空行: ^$ 匹配所有的单词: [A-Z a-z]* 匹配任一非字母型字符: [^A-Z a-z] 包含八个字符的行: ^……..$(8 个 .)

Page 6: SHELL 脚本编程

Sed 命令 命令格式

sed ‘/pattern/ action’ files pattern: 正则表达式 action: 操作,包括 p 、 d 、 s

示例: 打印行: sed –n ‘/ 0\.[0-9][0-9]$/p’ fruit_prices.txt 删除行: sed ‘/^[Mm]ango/d’ fruit_prices.txt 执行替换 /pattern1/s/pattern2/pattern3/g :

sed ‘s/paech/peach/g fruit_prices.txt’ 使用多重 sed sed –e ‘cmd1’……-e ’cmdN’ files :

sed –e ‘s/paech/peach/’ –e ‘s/ *[0-9][0-9]\.[0-9][0-9]$/\$/’ fruit_prices.txt 在管道中使用 sed

Page 7: SHELL 脚本编程

awk 命令 命令格式

awk ‘/pattern/ {actions}’ files 示例:

字段编辑: awk –F: ‘{ print $1,$3}’ inputfiles或: awk –F: ‘{ printf “%s is %s\n”,$1,$3}’ inputfiles

执行指定模式的操作:awk ‘/ *\$[1-9][0-9]*\.[0-9][0-9] */ {print $0; next} /*\$0\.[0-9][0-9] */ {print $0}’ fruit_prices.txt

比较操作符: < 、 > 、 <= 、 >= 、 == 、 != 、 value ~ /pattern/ 、 value !~ /pattern/ (相关: && 、 || )awk ‘($2 ~ /^\$[1-9][0-9]*\.[0-9][0-9]$/) && ($3 < 75)’ { printf “……”}’ input_f

利用管道符将标准输入作为输入

Page 8: SHELL 脚本编程

shell 变量为使 shell 编程更加容易而且有效,系统提供了一系列

shell 变量,可以保存诸如文件名、路径名等有用信息,使系统获知用户相关设置 本地变量:在用户现在的 shell 生命期的脚本中使用,若

shell 启动另一个进程或退出,该变量值无效 环境变量:用于所有用户进程(子进程),环境变量可

以在命令行中设置,但用户注销时变量值丢失。可将此变量放入 .profile 文件中使每次登录使这些值都被初始化

特定变量参数 位置变量参数

Page 9: SHELL 脚本编程

本地变量 命名:可以任何不包含空白字元的字串来当做变量名称 设置: v-name=value 或 {v-name=value} 其中, = :设置实际值到 v-name ; + :若已设置 v-name ,重设

其值 ? :若未设置 v-name ,报错; :- :若未设置 v-name ,设置新 显示: echo 可以显示单个变量取值(变量使用时名字前加

$ ) 清除:可用 unset 命令清除变量,即: unset v-name 查看所有本地变量:可用 set 命令显示所有本地定义的变量 只读变量:在设值变量后加命令: readonly v-name , 即 将变量设为只读方式,任何人试图改变它均返回错误信息, 用 readonly 命令可察看所有只读变量

Page 10: SHELL 脚本编程

环境变量环境变量的设置和使用基本与本地变量相同,除了 环境变量设置时必须用 export导出,其格式为 V-NAME=value; export V-NAME ( 或舍去分号,分写成两行 )

查看所有环境变量使用 env 命令常用预留环境变量 EDITOR 设置编辑器,如: EDITOR=vi; export EDITOR PWD 当前路径名 MANPATH 保存系统上 man 文本目录,目录间用冒号分隔,如 MANPATH=/usr/apps/man:/usr/local/man;export MANPATH

Page 11: SHELL 脚本编程

特定变量参数 &位置变量参数有些变量用以表示脚本运行时的一些相关信息,这些变量一开始执

行脚本时就会设定,并且不能被修改,被称作特定变量参数。如: $0 当前脚本的文件名 $# 当前脚本的参数个数 $* 以一个单字符串显示所有向脚本传递的参数 $$ 脚本运行的当前进程 PID $! 后台运行的最后一个进程的 PID $? 显示最后命令的退出状态。 0 表示没有错误,其他任何值均表 明有错误 位置变量参数可以完成向一个 shell 脚本传递信息的功能,位置参数可任意多,但只有前 9 个被访问,以 $n 表示当前脚本的第 n个参数值,其中 n=1..9

Page 12: SHELL 脚本编程

变量引用在脚本中执行变量替换时最容易犯的错误就是由于引用错误。为防止引用时产生误解, shell 有一下引用类型

双引号“”:可引用除 $ 、 ` 、 \外任意字符或字符串,最好在反馈文本字符串时全使用双引号

单引号‘’:可引用引号里所有字符(包括引号) $ A=‘a’ $ echo $A 输出结果为 a $ echo “$A” 输出结果为

a $ echo ‘$A’ 输出结果为 $A反引号 `` :设置系统命令输出到变量, shell 将反引号内作为一个系

统命令并执行 $ echo `date` 输出系统时间 $ echo date 输出结果为

date反斜线 \ :屏蔽其下一字符的特殊含义( & * + ^ $ ` “ | ? ) $ echo * 打印当前整个目录列表 $ echo \* 输出结果为 *

Page 13: SHELL 脚本编程

流程控制shell 提供了用来控制程序执行流程的命令,用户可以用这些命

令建立非常复杂的程序。与传统语言不同的是, shell 用于指定条件值的不是布尔表达

式而是命令和字符串 控制流程包括:

条件测试 循环结构

Page 14: SHELL 脚本编程

条件测试 (1)test 命令 : test condition 或 [ condition ]用于检查某个条件是否成立,它可以进行数值、字符和文件三

个方面的测试,其测试符和相应的功能分别如下: 数值测试:

– eq :相等 – ge :数 1 大于等于数 2 – gt :数 1 大于数 2 – ne :不相等 – le :数 1 小于等于数 2 – lt :数 1 小于数 2

字符串测试:= :相等 != :不相等 – z 字符串:空串 – n 字符串:非空串

文件状态测试:-e 文件名:文件存在 -r 文件名:文件存在且可读-w 文件名:文件存在且可写 -x 文件名:文件存在且可执行-s 文件名:文件存在且非空 -d 文件名:文件存在且为目录-f 文件名:文件存在且为普通文件

逻辑操作符 shell 提供了与 (“-a”) 、或 (“-o”) 、非 (“ !” )三个逻辑操作符用于将测试条件连接起来,其优先级为:“!”最高,“ -a” 次之,“ -o”最低

Page 15: SHELL 脚本编程

条件测试 (2)shell 脚本中的条件分支是通过 if条件语句来实现 , 其格式为 if 条件命令串 1 then  条件 1 为真时的命令串elif 条件命令串 2 then 条件 1 为假、条件 2 为真时的命令串else  条件 1 、 2均为假时的命令fi 

例:文件拷贝输出检查 ifcp#!/bin/sh# ifcpif cp myfile myfile.bakthen echo “Good copy”else echo “`basename $0`:error”fi

其中 if语句必须以 fi 终止elif 和 else 部分可省略也可有多个 elif部分if语句各部分不能为空但可使用永远为真的空命令 “:”解决此问题运行结果:

•从 myfile 到 myfile.bak到文件拷贝正常$ sh ifcpGood copy•cp 命令没有完成拷贝$ sh ifcpifcp :error

Page 16: SHELL 脚本编程

条件测试 (3)if条件语句用于在两个选项中选定一项,而 case条件选择为用户提供了根据字符串或变量的值从多个选项中选择一项的方法 , 其格式为:case 值 in 模式 1) 若干命令行 1;;模式 2) 若干命令行 2;;……*) 其他命令行esac 

模式部分可能包括元字符 * 任意字符 ? 任意单字符 [..] 类或范围中任意字符

取值后面的单词必须为 in; 每个模式必须以“ )”结束 ; 取值可为变量或常数 ; 取值将检查匹配的每个模式,一旦匹配,将执行期间所有命令直至“;;”,之后不再继续其他模式,若无一匹配,使用 * 捕获该值

Page 17: SHELL 脚本编程

条件测试 (3续 )

例:提示 y 或 n#!/bin/sh#yornecho –n “Do you wish to proceed:”read ANScase $ANS iny|Y|yes|Yes) echo “yes is selected”;;n|N) echo “no is selected”exit 0;;*) echo “`basename $0` :Unkown”exit 1;;esac

执行结果:$ sh yornDo you wish to proceed:abyorn:Unkown $ sh yornDo you wish to proceed:yyes is selected

注: echo –n :输出结束时不换行read ANS :从标准输入设备读入并赋 值给本地变量 ANS exit 0 :退出 shell程序,其后数字为 返回状态, 0为成功, 1为错误

Page 18: SHELL 脚本编程

循环结构 (1)for 循环对一个变量所有可能的值都执行一个命令序列。一般格式为: for 变量名

[in 数值列表 ]do 若干命令行done

例 1 :循环备份 #!/bin/sh#forcpBAK=“.bak”for loop in `ls`do echo “copy $loop to $loop$BAK”cp $loop $loop$BAKdone执行结果$ sh forcpcopy a to a.bakcopy b to b.bak

假设变量名是 var,则数值列表给出的数值将顺序替换循环命令列表中的 $var。若省略in,则变量 var的取值为位置参数。对变量的每一个可能的赋值都将执行 do和 done之间的命令列表

例 2 :使用参数#!/bin/sh#forparamfor paramdoecho “$param”done执行结果$ sh forparam Hello KittyHelloKitty

Page 19: SHELL 脚本编程

循环结构 (2)

while 和 until均用命令的返回状态值来控制循环,格式分别为: while  若干命令行 1do若干命令行 2done

例:循环输出#!/bin/sh# whilereadNUM=0echo –n “enter: ”while [ $NUM –lt 5 ]doNUM=`expr $NUM + 1`echo –n “$NUM ”done

until 若干命令行 1do 若干命令行 2done

只要命令行 1最后一个命令的返回状态为真,就继续执行 do...done之间的“命令行 2”

until 和 while 的区别在于: while 循环在条件为真时继续执行,而 until 在条件为假时继续执行

执行结果$ sh whileread1 2 3 4 5注: expr :整数(字符串)的计算 expr argument operator argument 其中乘号必须用“ /” 屏蔽其特定含义

Page 20: SHELL 脚本编程

循环结构 (3)

break :立即终止当前循环的执行,跳出循环。若在嵌入循环中,可指定跳出的循环个数contiune :不跳出循环,仅是不执行本次循环后面的语句而立即开始下一次循环的执行这两个语句只有放在 do 和done之间才有效

例:跳出 case死循环脚本一直循环直到输入大于 3#!/bin/sh# breakout# : 即空命令while :do echo –n “Enter the number” read ANS case $ANS in 1|2|3) echo –n “$ANS ” ;; *) echo “wrong” break ;;esacdone

Page 21: SHELL 脚本编程

shell 函数 在 shell 中还可以将一组命令集或语句组成一个可用块,即 shell 函数。它与 shell 程序形式上是相似的,不同的是它不是一个单独的进程,而是 shell 程序的一部分

函数定义的基本格式为:[function] 函数名(){若干命令行}

调用函数的格式为: functionname param1 param2 ……

shell 函数可以完成某些例行的工作;可以有自己的退出状态(用return 可带返回值地返回脚本中函数调用下一条语句 );可以作为if 、 while 等控制结构的条件。

在函数定义时不用带参数说明,但在调用函数时可以带有参数,此时shell 将把这些参数分别赋予相应的位置参数 $1、 $2、 ...及 $*

Page 22: SHELL 脚本编程

shell 函数(续)例:函数返回值测试#!/bin/sh#funccheck(){if [ $1 = $2 ]then return 0else return 1fi}echo “Input two numbers”read a bif check $a $bthen echo "equal"else echo "unequal"fi

执行结果:

$ sh funcInput two numbers2 3unequal

$ sh funcInput two numbers2 2equal

Page 23: SHELL 脚本编程

That’s all

Thank you!