第 6 章 b-shell 及编程

70
第6第 B-Shell 第第第

Upload: urbano

Post on 15-Jan-2016

252 views

Category:

Documents


0 download

DESCRIPTION

第 6 章 B-Shell 及编程. 主要内容. 主要目的 编写 shell 脚本 程序 交互方式下 使用 shell 的流程 控制,编写复合命令 主要内容 元字符,如:引号 shell 的变量 替换,命令替换,文件名生成 shell 变量 流程控制 子程序. 主要特点. 主要特点 shell 编程风格和 C 语言等算法语言的区别 shell 是面向命令处理的语言,提供的流程控制结构通过对一些内部命令的解释实现 如同 C 语言设计思路一样, shell 本身设计得非常精炼,但是它提供了灵活的机制 shell 许多灵活的功能,通过 shell 替换实现 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 6 章  B-Shell 及编程

第 6 章 B-Shell 及编程

Page 2: 第 6 章  B-Shell 及编程

第 6章 第 2页

主要内容 主要目的

编写 shell脚本程序交互方式下使用 shell的流程控制,编写复合命令

主要内容元字符,如:引号shell的变量替换,命令替换,文件名生成shell变量流程控制子程序

Page 3: 第 6 章  B-Shell 及编程

第 6章 第 3页

主要特点 主要特点

shell编程风格和 C语言等算法语言的区别shell是面向命令处理的语言,提供的流程控

制结构通过对一些内部命令的解释实现如同 C语言设计思路一样, shell本身设计得

非常精炼,但是它提供了灵活的机制shell许多灵活的功能,通过 shell替换实现例如:流程控制所需的条件判断,四则运算,都由 shell之外的命令完成

Page 4: 第 6 章  B-Shell 及编程

6.1 启动 B-shell

Page 5: 第 6 章  B-Shell 及编程

第 6章 第 5页

启动交互式 B-shell 启动方法

注册 shell键入 sh 命令进入了 B-shell

自动执行的批处理文件当 sh 作为注册 shell 被启动时,自动执行用户主目录

下的 .profile 文件中命令,记作 $HOME/.profile类似 umask 之类的命令,应当写在 .profile 文件中

Page 6: 第 6 章  B-Shell 及编程

第 6章 第 6页

sh 脚本的执行 编辑文件 lsdir( 格式为文本文件 )

# ! /bin/shif [ $# = 0 ]then dir=.else dir=$1fifind $dir -type d –print

执行这一脚本 (script) 文件的方法 : sh<lsdirsh lsdirchmod u+x lsdir; ./lsdir /bin三种方法均启动程序 /bin/sh ,生成新进程

Page 7: 第 6 章  B-Shell 及编程

6.2 重定向与管道

Page 8: 第 6 章  B-Shell 及编程

第 6章 第 8页

输入重定向 <filename

从文件 filename 中获取 stdin例如 : sort < telno.txt

<<word 从 shell 获取数据直到再次遇到定界符 wordcat << TOAST* Now : `date`* My Home Directory is $HOMETOAST执行结果* Now : Sat Jul 27 14:47:56 Beijing 2006* My Home Directory is /usr/jiang定界符所界定内容加工处理 ( 等同双引号处理 ):

变量替换,命令替换不执行文件名生成

Page 9: 第 6 章  B-Shell 及编程

第 6章 第 9页

输出重定向 > filename

将 stdout重定向到文件 filename

2> filename将文件句柄 2 重定向到文件 filename

2>&1将文件句柄 2 重定向到文件句柄 1 指向的文件

sh 允许对除 0 , 1 , 2 外其它文件句柄重定向

Page 10: 第 6 章  B-Shell 及编程

第 6章 第 10页

输出重定向 ( 例 1) ls -l > file.list

将命令 ls 标准输出 stdout定向到文件 file.list 中 cc try.c -o try 2> try.bugs

将 cc 命令的 stderr重定向到文件 try.bugs 中 try > try.out 2>try.err try 1> try.out 2>try.err

将 try 程序执行后的 stdout和 stderr分别重定向到不同的文件

Page 11: 第 6 章  B-Shell 及编程

第 6章 第 11页

sh 输出重定向 ( 例 2) try >rpt 2>&1

stdout和 stderr均存入文件 rpt0123

...

终端

键盘 0123

...

终端

键盘

rpt

0123

...

终端

键盘

rpt

try 2>&1 >rptstderr定向到终端, stdout重定向到文件

0123

...

终端

键盘 0123

...

终端

键盘 0123

...

终端

键盘

rpt

Page 12: 第 6 章  B-Shell 及编程

第 6章 第 12页

输出重定向 ( 例 3: 源程序 ) 缓冲 I/O

#include <stdio.h>char *msg = "Msg from file descripter 5\n";main(){ FILE *f = fdopen(5, "w"); if (f) fprintf(f, "%s", msg);}

原始 I/Ochar *msg = "Msg from file descripter 5\n";main(){ write(5, msg, strlen(msg));}

Page 13: 第 6 章  B-Shell 及编程

第 6章 第 13页

输出重定向 ( 例 3: 程序执行 ) 编译和执行

cc msg.c -o msg./msg./msg 5>&1

./msg >rpt 5>&1文件句柄 5 重定向到文件句柄 1 指向的文件012345

...

终端

键盘 012345

...

终端

键盘

rpt

012345

...

终端

键盘

rpt

Page 14: 第 6 章  B-Shell 及编程

第 6章 第 14页

管道 ls -l | grep '^d' 前一命令的 stdout作后一命令的 stdin cc try.c -o try 2>&1 | more 前一命令的 stdout+stderr作为下一命令的 stdin

0123

...

终端

键盘 0123

...

终端

键盘 0123

...

终端

键盘

PIPE PIPE

Page 15: 第 6 章  B-Shell 及编程

6.3 变量

Page 16: 第 6 章  B-Shell 及编程

第 6章 第 16页

sh 变量 存储的内容

字符串 ( 对于数字串来说,不是二进制形式 )在执行过程中其内容可以被修改

变量名第一个字符必须为字母其余字符可以是字母,数字,下划线

Page 17: 第 6 章  B-Shell 及编程

第 6章 第 17页

变量的赋值和引用 简单赋值与引用

addr=20.1.1.254 echo $addr 注意:赋值作为单独一条命令,等号两侧不许多余空格引用 addr 变量 $addr , echo 执行前, sh 完成变量替

换 赋值时,等号右侧字符串中含有特殊字符,

unit=”Beiyou University”echo $unit

引用未定义变量,变量值为空字符串echo Connect to $proto Networkproto=TCP/IPecho Connect to $proto Network

Page 18: 第 6 章  B-Shell 及编程

第 6章 第 18页

命令 echo 语法与功能

echo arg1 arg2 arg3 ...打印各命令行参数,每两个间用一空格分开,最后打印换行符

不可打印字符 ( 转义 ) : Linux 需加选项 -eecho 支持 C 语言字符串常数描述格式的转义和 \c

\c 打印完毕,不换行 \b 退格 \n 换行 \r 回车 \t 水平制表 \\ 反斜线 \nnn  八进制描述的字符 ASCII码

举例echo Beijing Chinaecho "Beijing China"echo '\065' 打印 5echo \\101 打印 Aecho "\r$cnt \c"

Page 19: 第 6 章  B-Shell 及编程

第 6章 第 19页

read: 读用户的输入内部命令 read:变量取值的另外一种方

法从标准输入读入一行内容赋值给变量例:读取用户的输入,并使用输入的信息。

$ read name ccp.c$ echo $nameccp.c$ ls -l $name-rw-r--r-- 1 jiang usr 32394 May 27 10:10 ccp.c$

Page 20: 第 6 章  B-Shell 及编程

第 6章 第 20页

脚本程序中的行编辑 (1)假设应用程序 myap 运行时从 myap.cfg 中读取配置参数$ cat myap.cfg ID 3098SERVER 192.168.0.251TCP-PORT 3450TIMEOUT 10LOG-FILE /usr/adm/myap.log$ chmod u+x config.ap; cat config.ap #!/bin/shecho 'Input IP address of server computer: \c'read addred myap.cfg > /dev/null <<TOAST/SERVER.diSERVER $addr.wqTOAST

Page 21: 第 6 章  B-Shell 及编程

第 6章 第 21页

脚本程序中的行编辑 (2)$ ./config.ap Input IP address of server computer: 202.112.67.213 $ cat myap.cfg ID 3098SERVER 202.112.67.213TCP-PORT 3450TIMEOUT 10LOG-FILE /usr/adm/myap.log$

Page 22: 第 6 章  B-Shell 及编程

第 6章 第 22页

环境变量和局部变量 默认类型

所创建的 shell变量,默认为局部变量 内部命令 export

局部变量转换为环境变量,例如:export proto

局部变量和环境变量shell启动的子进程继承环境变量,不继承局部变量子进程对环境变量的修改,不影响父进程中同名变量

相关命令 set/env 内部命令 set 列出当前所有变量及其值

包括环境变量和局部变量外部命令 /bin/env 列出环境变量及其值

Page 23: 第 6 章  B-Shell 及编程

第 6章 第 23页

环境变量: shell/C 程序$chmod u+x stat.report; cat stat.reportecho My Computer Connected to $proto Networks$ cc myap.c -o myap; cat myap.cmain(){ char *envstr = getenv(”proto”); printf(”Protocol is %s\n”, envstr ? envstr : “???”);}$proto=TCP/IP$./stat.report 启动一个子进程 shMy Computer Connected to Networks$./myap      启动一个子进程 myapProtocol is ???$export proto$./stat.reportMy Computer Connected to TCP/IP Networks$./myapProtocol is TCP/IP

Page 24: 第 6 章  B-Shell 及编程

第 6章 第 24页

系统的环境变量 创建

登录后系统自动创建一些环境变量影响应用程序运行 HOME :用户主目录的路径名 PATH :命令查找路径

与 DOS 不同的是 , 它不首先搜索当前目录PATH=/bin:/usr/bin:/etcPATH=./:/bin:/usr/bin:/etc 先搜索当前目录PATH=/:bin/usr/bin:/etc:./ 后搜索当前目录

PS1 和 PS2 :主提示符和副提示符 sh副提示符:当一个命令在一行内输不完需几行输入一

个命令时,第 2 行及其它行用副提示符 TERM :终端类型

全屏幕操作的软件 ( 如 vi) ,使用它搜索终端库

Page 25: 第 6 章  B-Shell 及编程

6.4 替换

Page 26: 第 6 章  B-Shell 及编程

第 6章 第 26页

shell 替换 Shell 的替换工作 : 先替换命令行再执行命令

文件名生成变量替换命令替换

文件名生成遵循文件通配符规则,按照字典序排列如 : ls *.c 文件名替换后实际执行 ls a.c x.c

变量替换 ls $HOMEecho ”My home is $HOME, Terminal is $TERM”

Page 27: 第 6 章  B-Shell 及编程

第 6章 第 27页

shell 替换 : 命令替换 用反撇号

now=`date` 以命令 date 的 stdout 替换 `date`./arg `date`

实际执行./arg Sun Dec 4 14:54:38 Beijing 2006

frames=`expr 5 + 13`echo $frames18count=10count=`expr $Count + 1`echo $count11

Page 28: 第 6 章  B-Shell 及编程

第 6章 第 28页

shell 内部变量:位置参数 $0

脚本文件本身的名字 $1

1 号命令行参数 $#

命令行参数的个数 "$*"

”$1 $2 $3 $4 ...” "$@"

”$1” ”$2” ”$3” …

Page 29: 第 6 章  B-Shell 及编程

第 6章 第 29页

位置参数使用举例$ cat paramecho $# echo "Usage: $0 arg1 arg2 ..."./arg "$@"./arg "$*"$ ./param Copy Files to $HOME 4Usage: ./param arg1 arg2 ...0:[./arg]1:[Copy] 2:[Files]3:[to]4:[/usr/jiang]0:[./arg]1:[Copy Files to /usr/jiang]

Page 30: 第 6 章  B-Shell 及编程

6.5 元字符

Page 31: 第 6 章  B-Shell 及编程

第 6章 第 31页

shell 元字符 (1) 空格 , 制表符

命令行参数的分隔符 回车

执行键入的命令 > < |

重定向与管道 ( 还有 ||) ;

用于一行内输入多个命令 ( 还有 ;;) &

后台运行 ( 还有 &&) $

引用 shell 变量

Page 32: 第 6 章  B-Shell 及编程

第 6章 第 32页

shell 的元字符 (2) `

反向单引号,用于命令替换 * [] ?

文件通配符 (echo "*" 与 echo * 不同) \

取消后继字符的特殊作用 ( 转义 )若后继字符为非特殊字符,则不起作用

( ) 用于定义 shell 函数 , 以及定义命令表

分隔符( )><|;& 等除了它们自身的特殊含义外还同时起到

分隔符的作用 ( 同空格 )

Page 33: 第 6 章  B-Shell 及编程

第 6章 第 33页

转义符 反斜线作转义符,取消其后元字符的特殊作用 如果反斜线加在非元字符前面,反斜线跟没有一样find / -size +100 \( -name core -o -name \*.tmp \) -exec rm -f {} \;ls -l > file\ listvi 2\>\&1echo Unix\ \ \ System\ V 与 echo Unix System Vecho * 与 echo \*echo $HOME 与 echo \$HOMEecho \A 与 echo Aecho Windows Directory is C:\Windows\WORK.DIRecho Windows Directory is C:\\Windows\\WORK.DIR

Page 34: 第 6 章  B-Shell 及编程

第 6章 第 34页

元字符:引号 双引号 "

除 $ 和 ` 外特殊字符的特殊含义被取消需要的转义 \“ \$ \` \\echo * 与  echo "*“

单引号 ' 对所括起的任何字符,不作特殊解释echo "My home dir is $HOME"echo 'My home dir is $HOME'

Page 35: 第 6 章  B-Shell 及编程

第 6章 第 35页

转义符与引号及反撇号 配对的双引号中

\" 代替双引号自身 \\ 代表反斜线自身 \` 代替反撇号自身 \$ 代表美元符自身其它情况下的反斜线保持原文不变

echo "\A" 与 echo \Aecho "\$" 与 echo \$

配对的反撇号中 \\ 代表反斜线自身 \` 代替反撇号自身其它情况下的反斜线保持原文不变

配对的单引号 \ 代表反斜线自身不许任何转义,不许出现单引号

Page 36: 第 6 章  B-Shell 及编程

第 6章 第 36页

转义符使用举例$ echo 'Don'\''t remove Peter'\''s DOS dir "C:\PETER"!'Don't remove Peter's DOS dir "C:\PETER"!$ echo "jiang's \$HOME is \"$HOME\""jiang's $HOME is "/usr/jiang"$ echo "\`\`pipeline'' is commands separated by |"``pipeline'' is commands separated by |

Page 37: 第 6 章  B-Shell 及编程

第 6章 第 37页

反撇号内的转义处理 例:给出程序名字,中止系统中正在运行的进程$ ps -e | grep myap 31650 pts/2 0:00 myap$ kill 31650ps -e | awk '/[0-9]:[0-9][0-9] myap$/{printf("%d ",$1)}'ps -e | awk "/[0-9]:[0-9][0-9] $1\$/{printf(\"%d \",\$1)}"kill `ps -e | awk "/[0-9]:[0-9][0-9] $1\\$/{printf(\\"%d \\",\\$1)}"`$ cat kPIDs=`ps -e|awk "/[0-9]:[0-9][0-9] $1\\$/{printf(\\"%d \\",\\$1)}"`echo "kill $PIDs"kill $PIDs$ chmod u+x k$ ps -e | grep myap27248 pts/2 0:00 myap31714 pts/2 0:00 myap36926 pts/2 0:00 myap$ ./k myapkill 27248 31714 36926

Page 38: 第 6 章  B-Shell 及编程

6.6 条件判断

Page 39: 第 6 章  B-Shell 及编程

第 6章 第 39页

条件 条件判定的依据

判定一条命令是否执行成功,判断方法 : 命令执行的返回码, 0:TRUE( 成功 ) ,非 0:FALSE( 失败 )

$ ls -d xyzxyz$ echo $? $? 上一命令的返回码, shell 自定义变量0$ ls -d xyz1xyz1: not found$ echo $?2

用管道线连接在一起的若干命令的执行返回码为最后一个命令执行的返回码

Page 40: 第 6 章  B-Shell 及编程

第 6章 第 40页

最简单的条件判断用 && 或 || 连结两个命令 cmd1 && cmd2

若 cmd1 执行成功 ( 返回码为 0) 则执行 cmd2 ,否则不执行 cmd2

cmd1 || cmd2 cmd1 执行失败 ( 返回码不为 0) 则执行 cmd2 ,否则

不执行 cmd2

$ ls -d xdir >/dev/null && echo FOUNDFOUND若没有目录 ydir

$ ls -d ydir >/dev/null 2>&1 ||echo No ydirNo ydir

Page 41: 第 6 章  B-Shell 及编程

第 6章 第 41页

命令 true 与 false /bin/true

返回码总为 0 /bin/false

返回码总不为 0 有的 shell 为了提高效率,将 true 和 false 设置

为内部命令

Page 42: 第 6 章  B-Shell 及编程

第 6章 第 42页

命令 test 与 [ 区别

命令 /usr/bin/[ 要求其最后一个命令行参数必须为 ]

除此之外 /usr/bin/[ 与 /usr/bin/test 功能相同 Linux 中 /usr/bin/[ 是一个指向 test 的符号连接

注意:不要将方括号理解成一个词法符号举例

test -r /etc/motd [ -r /etc/motd ]

Page 43: 第 6 章  B-Shell 及编程

第 6章 第 43页

命令 test :文件特性检测 文件特性检测

-f 普通文件 -d 目录文件 -r 可读 -w 可写 -x 可执行 -s size>0

例test -r /etc/motd && echo readable[ -r /etc/motd ] && echo readable

Page 44: 第 6 章  B-Shell 及编程

第 6章 第 44页

命令 test :字符串和整数 字符串比较

-n str str 串长度大于 0 str1 = str2 str1 与 str2 串相等 str1 != str2 str1 串与 str2 串不等

注意 : 等号和不等号两侧的空格不可少 [ -n "$a" ] || echo a=NULL 注意 :$a 的引号 test $# = 0 && echo "No argument"

整数的比较 -eq = -ne ≠ -gt > -ge ≥ -lt < -le ≤

例 : test `ls | wc -l` -ge 100 && echo "Too many files"

Page 45: 第 6 章  B-Shell 及编程

第 6章 第 45页

命令 test :逻辑运算 逻辑运算

! NOT (非) -o OR (或)-a AND (与)

例 : [ ! -d $cmd -a -x $cmd ] && $cmd 注意:必需的空格不可省略

$ cat hereecho ”count=$#”[ $#=2 ] && echo Here$ ./here *.ccount=9Here

Page 46: 第 6 章  B-Shell 及编程

第 6章 第 46页

复合命令 复合命令:条件满足时,执行若干个命令

使用 { } 或者 ( )pwd DIR=/usr/bin[ -d $DIR ] && { cd $DIR echo ”Current Directory is `pwd`” echo ”`ls | wc -l` files”} pwd 执行结果/usr/jiangCurrent Directory is /usr/bin400 files /usr/bin

Page 47: 第 6 章  B-Shell 及编程

第 6章 第 47页

{ } 与 ( ) {} 与 () 的书写规则

(list) 在子 shell中执行命令表 list{ list;} 在当前 shell中执行命令表 list

注意 : 左花括号后面必须有一个空格 {} 与 () 的区别

如果将上例中的 {} 改成 () ,那么执行结果如下 :/usr/jiangCurrent Directory is /usr/bin400 files /usr/jiang

Page 48: 第 6 章  B-Shell 及编程

第 6章 第 48页

复合命令:举例 使用 {} 时,多行并为一行不要漏掉必需的空格

和分号[ -f core ] && { echo "rm core" rm core}

写成一行应当为[ -f core ] && { echo "rm core";rm core;}

Page 49: 第 6 章  B-Shell 及编程

第 6章 第 49页

条件结构 if 语法

if condition

then list

elif condition

then list

else list

fi其中 if/then/elif/else/fi 为关键字 ( 内部命令 )当条件判断后需要两个或多个分支时, && 和 || 就

不够了,这时应当用 if 结构

Page 50: 第 6 章  B-Shell 及编程

第 6章 第 50页

条件结构 if :举例$ cat errmonitor

LOGFILE=./errlogdate>>$LOGFILEif test -w errfilethen cat errfile>>$LOGFILE rm errfileelse echo ”No error”>>$LOGFILEfithen 行可和 cat 行合并成一行if 行不可以和 then 行直接合并成一行将两行合并 : 分号使得一行内可以输入多条命令

if test -r errfile; then

Page 51: 第 6 章  B-Shell 及编程

第 6章 第 51页

case 结构 基于文件名匹配基础上的多条件分支,语法 :

case word in pattern1) list1;; pattern2) list2;; ...esacword 与 pattern 匹配:使用 shell的文件名匹配规则;; 是一个整体,不能在两分号间加空格,也不能用

两个连续的空行代替可以使用竖线表示多个模式word 与多个模式匹配时,执行遇到的第一个命令表

Page 52: 第 6 章  B-Shell 及编程

第 6章 第 52页

case 结构:举例 语法

case "$1" inSTART|start) ... ( 一段程序 ) ;;STOP|stop) ... ( 一段程序 ) ;;*) echo "Usage: $0 [start|stop]" ;;esac

注意:本例中 case 句中 $1 要加上双引号

Page 53: 第 6 章  B-Shell 及编程

6.7 循环结构

Page 54: 第 6 章  B-Shell 及编程

第 6章 第 54页

while 结构 语法

while condition do list

done 例 1

while test -r lockfiledo sleep 5done

下例有错while test -r lockfile do sleep 5done

例 2while [ -r lockfile ]; do sleep 5;done

Page 55: 第 6 章  B-Shell 及编程

第 6章 第 55页

命令 expr :表达式计算 功能:求表达式的值

shell本身不提供数学运算和字符串运算的能力,这些运算借助命令 expr 完成

算数运算 + - * / % ()

注意应该转义的地方必须加反斜线转义应该有空格的地方不允许漏掉。

例 1:求变量 a*(b+c)正确的写法为 expr $a \* \( $b + $c \)

Page 56: 第 6 章  B-Shell 及编程

第 6章 第 56页

命令 expr :算数运算 ( 例 )if [ $# = 0 ]then echo "Usage: $0 : <number>"else count=$1 while [ $count -gt 0 ] do count=`expr $count - 1` echo -e "\015 $count \c" sleep 1 done fi

Page 57: 第 6 章  B-Shell 及编程

第 6章 第 57页

命令 expr :字符串运算 用法 : expr string : pattern

正则表达式 pattern 匹配字符串 string ,打印匹配长度pattern 中用 \( 和 \) 括起一部分,能匹配时打印括号内

能匹配的部分,否则为空字符串举例

expr 123 : "[0-9]*" 结果为 3expr A123 : "[0-9]*" 结果为 0

Page 58: 第 6 章  B-Shell 及编程

第 6章 第 58页

命令 expr :字符串运算 ( 例 ) 设 tty 命令输出类似 /dev/tty6 的结果

expr `tty` : "/dev/tty\(.*\)"expr `tty` : /dev/tty\\\(.\*\\\)termno=`expr \`tty\` : /dev/tty\\\\\\(.\\*\\\\\\)`

expr "$unit" : ".*" 返回变量 unit的长度expr `pwd` : '.*/\([^/]*\)$' 截取路径名的最后一个分量

Page 59: 第 6 章  B-Shell 及编程

第 6章 第 59页

for 结构 语法 1

for name in word1 word2 ... do listdone

语法 2for name do listdone相当于for name in $1 $2 ... do listdone

Page 60: 第 6 章  B-Shell 及编程

第 6章 第 60页

for 结构:程序举例 1 例 1 :一段开机时自动执行的批处理程序

if [ -d /etc/rc.d ]then for cmd in /etc/rc.d/*/* /etc/rc.d/* do [ ! -d $cmd -a -x $cmd ] && $cmd donefi

Page 61: 第 6 章  B-Shell 及编程

第 6章 第 61页

for 结构:程序举例 2 例 2 :将命令行参数逆序显示出来

list=” ”for argdo list=”$arg $list”doneecho ”$list”

Page 62: 第 6 章  B-Shell 及编程

第 6章 第 62页

break 内部命令 break

循环结构 for/while 中使用,中止循环例 :将命令行参数逆序输出count=$#cmd=echowhile truedo cmd=”$cmd \$$count” count=`expr $count - 1` [ $count -eq 0 ] && breakdoneeval $cmd

内部命令 eval将实参作为 shell 的输入读入,再经过一轮变量替

换 / 文件名生成 / 命令替换后,执行所得的命令

Page 63: 第 6 章  B-Shell 及编程

第 6章 第 63页

continue 内部命令 continue

在循环结构 for/while 中使用,提前结束本轮循环例 :将命令行参数逆序输出count=$#cmd=echowhile truedo cmd=”$cmd \$$count” count=`expr $count - 1` [ $count -gt 0 ] && continue eval $cmd exit 0 done

内部命令 exit终止当前 shell进程

Page 64: 第 6 章  B-Shell 及编程

6.8 函数

Page 65: 第 6 章  B-Shell 及编程

第 6章 第 65页

shell 函数 语法

name() { list;}参数

调用时函数名后附加上 0 到多个参数在函数体内部以 $1 , $2 , ... 或 $* , $@ 方式引

用 返回值

函数体内用 return 使函数有返回码,返回码 0 代表成功,非零表示失败

函数内部可以创建和修改变量,函数返回后其它程序访问

Page 66: 第 6 章  B-Shell 及编程

第 6章 第 66页

Shell 的注释 shell 中使用 # 号作注释

# 号出现在一个单词的首部,那么,从 # 号至行尾的所有字符被忽略

Page 67: 第 6 章  B-Shell 及编程

第 6章 第 67页

shell 函数举例get_val() # Usage: get_val 变量名 提示 默认值 取值表{ while true do echo -e "$2 [$3] : \c" ; read val [ "$val" = "" ] && val=$3 for i in $4 do [ "$val" = "$i" ] && break 2 done echo "**** Invalid choice $val, must be in $4" done eval "$1=$val" } # main() get_val INTR "Interrupt Number" 10 "5 10 11 12 14" get_val PORT "I/O Base Address" 800 "512 560 800" get_val BAUD "Baud Rate" 9600 "2400 9600 57600" echo "INTR=$INTR PORT=$PORT BAUD=$BAUD"

Page 68: 第 6 章  B-Shell 及编程

6.9 shell 开关和位置变量

Page 69: 第 6 章  B-Shell 及编程

第 6章 第 69页

shell 内部开关 shell 内部开关

-x 执行命令前打印出 shell 替换后的命令及参数,为区别于正常的 shell 输出,前面冠以 + 号

+x 取消上述设置-u 当引用一个未定义的变量时,产生一个错误+u 当引用一个未定义的变量时,认为是一个空串

Page 70: 第 6 章  B-Shell 及编程

第 6章 第 70页

shell 内部开关程序举例 例: cat chmod1

set -xecho "$*"for ido [ -f $i ] && { chmod a+r $i eoho "$i is readable" }done

内部开关的设置方法set -x 也可以省略,使用命令 sh -x chmodl a*交互式 shell 也可以使用 set -x/set +x使用 shell 的 -x 选项对 shell 程序调试非常有用