18.1 退出状态

#任何命令进行时都将返回一个退出状态
#如果要观察其退出状态,使用最后状态命令
$ echo $?#主要有四种退出状态
#最后命令退出状态$?和控制次序命令($$、||)
#其余两种是处理shell脚本或shell退出及相应退出状态或函数返回码#要退出当前进程,shell提供命令exit,一般格式为:
exit n
#如果只在命令提示符下键入exit,假定没有在当前状态创建另一个shell,将退出当前shell
#如果在脚本中键入exit,shell将试图(通常是这样)返回上一个命令返回值
#相对脚本和一般系统命令最重要的有两种,即
#退出状态0 退出成功,无错误
#退出状态1 退出失败,某处有错误

18.2 控制结构

18.2.1 流控制

if、then、else语句提供条件测试。这些测试返回值或者为真(0),或者为假(1)

case语句允许匹配模式、单词或值

18.2.2 循环

for循环 依次处理列表内信息,直至循环耗尽

Until循环 此循环语句不常使用,until循环直至条件为真。条件部分在循环末尾部分

While循环 while循环当条件为真时,循环执行,条件部分在循环头

流控制语句的任何循环均可嵌套使用

18.3 if then else语句

if语句测试条件,测试条件返回真(0)或假(1)后,可相应执行一系列语句

if语句格式:
if  条件1then  命令1elif  条件2then  命令2else  命令3
fiif语句的各部分功能
if  条件1  #如果条件1为真then  #那么
命令1  #执行命令1elif  条件2  #如果条件1不成立then  #那么
命令2  #执行命令2else  #如果条件1、2均不成立
命令3  #那么执行命令3
fi  #完成#if语句必须以单词fi终止

18.3.1 简单的if语句

#最普通的if语句是
if 条件
then 命令
fi#使用if语句时,必须将then部分放在新行,否则会产生错误
#如果要不分行,必须使用命令分割符
if 条件; then命令
fi#测试10是否小于12
#! /bin/bash
if [ "10" -lt "12" ]
thenecho "Yes, 10 is less than 12"
fi

18.3.2 变量值测试

#通过测试设置为接受用户输入的变量可以测知用户是否输入信息
#下面的例子中测试用户键入return键后变量name是否包含任何信息$pg iftest2#!/bin/bash
echo -n "Enter your name"
read NAME
if [ "$NAME" = "" ] ; thenecho "You did not enter any information"
fi$ iftest2

18.3.3 grep输出检查

不必拘泥于变量或数值测试,也可以测知系统命令是否成功返回。对grep使用if语句找出grep是否成功返回信息

#下面的例子中grep用于查看Dave是否在数据文件data.file中
#注意'Dave\>'用于精确匹配$ pg grepif#! /bin/bash
if grep 'Dave\>' data.file > /dev/null 2>&1
thenecho "Great Dave is in the file"
elseecho "No Davve is not in the file"
fi$ grepif
#上面的例子中,grep输出定向到系统垃圾堆
#如果匹配成功,grep返回0,将grep嵌入if语句;如果grep成功返回,if部分为真

18.3.4 用变量测试grep输出

#可以用greo作字符串操作
#下面的脚本中,用户输入一个名字列表,grep在变量中查找,要求其包含人名Peter$ pg grepstr#! /bin/bashecho -n "Enter a list of names:"
read list
if echo $list | grep "Peter" > /dev/null 2>&1
thenecho "Peter is here"
elseecho "Peter's not in the list. No comment!"
fi

18.3.5 文件拷贝输出检查

下面测试文件拷贝是否正常,如果cp命令并没有拷贝文件myfile到myfile.bak,则打印错误信息。注意错误信息中'basename $0'打印脚本名

$ pg ifcp
#! /bin/bashif cp myfile myfile.bak; thenecho "good copy"
elseecho "'basename $0':error could not copy the files" >&2
fi$ ifcp
cp: myfile: No such file or directory
ifcp: error could not copy the files#要去除系统产生的错误和系统输出,只需简单的将标准错误和输出重定向即可$ pg ifcp
#! /bin/bashif cp myfile myfile.bak > /dev/null 2> thenecho "good copy"
elseecho "'basename $0': error could not copy the files" >&2
fi#脚本运行时,所有输出包括错误重定向至系统垃圾堆
$ ifcp
ifcp: error could not copy the files

18.3.6 当前目录测试

当运行一些管理脚本时,可能要在根目录下运行它,特别是移动某种全局文件或进行权限改变时。一个简单的测试可以获知是否运行在根目录下

#下面脚本中变量DIRECTORY使用当前目录的命令替换操作,然后此变量值与"/"字符串比较(/为根目录)
#如果变量值与字符串不等,则用户退出脚本,退出状态为1意味错误信息产生$ pg ifpwd#! /bin/bash
DIRECTORY='pwd'
if [ "DIRECTORY" != "/" ]; thenecho "You need to be in the root directory not $DIRECTORY to run this script" >&2exit 1
fi

18.3.7 文件权限测试

#可以用if语句测试文件权限
#下面简单测试文件test.txt是否被设置到变量LOGNAME
$ pg ifwr#!/bin/bash
LOGFILE=test.txt
echo $LOGFILE
if [ ! -w "LOGFILE" ]; thenecho "You cannot write to $LOGFILE" >&2
fi

18.3.8 测试传递到脚本中的参数

#if语句可以用来测试传入脚本中参数的个数
#使用特定变量$#,表示调用参数的个数#以下测试确保脚本有三个参数,如果没有,则返回一个可用信息到标准错误,然后代码退出并显示退出状态。如果参数数目等于3,则显示所有参数$ pg ifparam
#! /bin/bashif [ $# -lt 3 ]; then  #如果输入的参数<3个,则输出错误信息并退出脚本echo "Usage: 'basename $0' arg1 arg2 arg3" >&2exit 1
fiecho "arg1:$1"
echo "arg2:$2"
echo "arg3:$3"#如果只传入两个参数,则显示一可用信息,然后脚本退出
$ ifparam cup medal
Usage:ifparam arg1 arg2 arg3#传入三个参数
$ ifparam cup medal trophy
arg1:cup
arg2:medal
arg3:trophy

18.3.9 决定脚本是否为交互模式

#有时需要知道脚本运行是交互模式(终端模式)还是非交互模式(cron或at)
#脚本也许需要这个信息以决定从哪里取得输入以及输出到哪里
#使用test命令并带入-t选项很容易确认这一点
#如果test返回值为1,则为交互模式$ pg ifinteractive
#!/bin/bashif [ -t ];thenecho "We are interactive with a terminal"
elseecho "We must be running from some background process probably cron or at"
fi

18.3.10 简单的if else语句

这个if语句有可能是使用最广泛的
if  条件
then  命令1
else命令2
fi
#使用fi语句的else部分可在条件测试为假时采取适当动作

18.3.11 变量设置测试

#下面的例子测试环境变量EDITOR是否已设置
#如果EDITOR变量为空,将此信息通知用户
#如果已设置,在屏幕上显示编辑类型$ pg ifeditor
#! /bin/bashif [ -z $EDITOR ];thenecho "Your EDITOR environment is not set"
elseecho "Using $EDITOR as the default editor"
fi

18.3.12 检测运行脚本的用户

#下面例子中,环境变量用于测试条件,即LOGNAME是否包含root值
#这类语句是加在脚本开头作为一安全性准则的普遍方法
#如果变量不等于root,返回信息到标准错误输出即屏幕,也就是通知用户不是root,脚本然后退出,并带有错误值1
#如果字符串root等于LOGNAME变量,else部分后面语句开始执行
#实际上,脚本会继续进行正常的任务处理,这些语句在fi后面,因为所有非root用户在脚本的前面测试部分已经被剔出掉了$ pg ifroot
#!/bin/bashif [ "$LOGNAME" != "root" ]
thenecho "You need to be root to run this script" >&2exit 1
elseecho "Yes indeed you are $LOGNAME proceed"
fi

18.3.13 将脚本参数传入系统命令

#可以向脚本传递位置参数,然后测试变量
#如果用户在脚本名字后键入目录名,脚本将重设$1特殊变量为一更有意义的名字
#这里需测试目录是否为空,如果目录为空,ls-A将返回空,然后对此返回一信息$ pg ifdirec
#!/bin/bashDIRECTORY = $1
if [ "'ls -A $DIRECTORY'" = ""]; thenecho "$DIRECTORY is indeed empty"
elseecho "$DIRECTORY is not empty"
fi#也可以用下面的脚本替代上面的例子并产生同样的结果
$ pg ifdirec2
#! /bin/bashDIRECTORY = $1
if [ -z "'ls -A $DIRECTORY'" ]
thenecho "$DIRECTORY is indeed empty"
elseecho "$DIRECTORY is not empty"
fi

18.3.14 null:命令用法

#if语句各部分不能为空,但是一些语句已经可以这样做
#shell提供了:空命令
#空命令永远为真
#回到前面的例子,如果目录为空,可以只在then部分加入命令$ pg ifdirectory
#! /bin/bash
DIRECTORY = $1
if [ "'ls -A $DIRECTORY'" = "" ]
thenecho "$DIRECTORY is indeed empty"else :  #空命令,什么都不做,空命令永远为真
fi

18.3.15 测试目录创建结果

#下面的脚本接受一个参数,并用之创建目录
#然后参数被传入命令行,重设给变量DIRECTORY,最后测试变量是否为空
if [ "$DIRECTORY" = "" ]
#也可以用
if [ $# -lt 1 ]
#来进行更普遍的参数测试#如果字符串为空,返回一可用信息,脚本退出
#如果目录已经存在,脚本从头至尾走一遍,什么也没做
#创建前加入提示信息,如果键入Y或y,则创建目录,否则使用空命令表示不采取任何动作
#使用最后命令状态测试创建是否成功执行,如果失败,返回相应信息$ pg ifmkdir
#! /bin/bashDIRECTORY = $1
if [ "DIRECTORY" = "" ]  #如果字符串为空
thenecho "Usage: 'basename $0' directory to create" >&2exit 1
fi
if [ -d $DIRECTORY ]  #检测是不是目录,是的话什么也不做,不是的话则创建
then: # do nothing  空命令为真,什么也不做
elseecho "The directory does exist"echo -n "Create it now?[y..n]:"read ANSif [ "ANS"="y" ] || [ "ANS"="Y" ]thenecho "creating now"if [ $? != 0 ];thenecho "Errors creating the directory $DIRECTORY" >&2exit 1 fielse:  #do nothing  空命令为真,什么也不做fi
fi

18.3.16 另一个拷贝实例

#在另一个拷贝实例中,脚本传入两个参数(应该包含文件名)
#系统命令cp将$1拷入$2,输出至/dev/null
#如果命令成功,则仍使用空命令并且不采取任何动作
#另一方面,如果失败,在脚本退出前要获知此信息$ pg ifcp2
#! /bin/bashif cp $1 $2 > /dev/null 2>$1  #将$1拷入$2,输出至/dev/null
then:  #命令成功,什么也不做
else#失败则打印失败信息echo "'basename $0':ERROR failed to copy $1 to $2 "exit 1
fi#脚本运行,没有拷贝错误
$ cp2 myfile.lex myfile.lex.bak#脚本运行,带有拷贝错误
$ ifcp2 myfile.lexx myfile.lex.bak
#返回错误信息
ifcp2:ERROR failed to copy myfile.lexx myfile.lex.bak
#下面的脚本用sort命令将文件accountx.qtr分类,并输出至系统垃圾堆
#成功之后不采取任何动作。如果失败,通知用户$ pg ifsort
#! /bin/bashif sort accounts.qtr > /dev/null
then:
elseecho "'basename $0': Oops..errors could not sort accounts.qtr"
fi

13.3.18 测试和设置环境变量

#前面已经举例说明了如何测试环境变量EDITOR是否被设置
#现在如果为设置,则进一步为其赋值,脚本如下$ pg ifseted
#! /bin/bashif [ -z $EDITOR ];thenecho "Your EDITOR environment is not set"echo "I will assume you want to use vi..OK"echo -n "Do you wish to change it now?[y..n]"read ANSif [ "$ANS" = "y"] || [ "$ANS" = "Y" ];thenecho "enter your editor type:"read EDITORif [ -z $EDITOR ] || [ "$EDITOR" = ""];thenecho "No,editor entered,using vi as default"EDITOR=viexport EDITORfiEDITOR = $EDITORexport EDITORecho "setting $EDITOR"fi
elseecho "Using vi as the default editor"EDITOR=viexport vi
fi#脚本工作方式如下:首先检查是否设置了该变量,如果已经赋值,输出信息提示使用vi作为缺省编辑器
#如果未赋值,则提示用户,询问其是否要设置该值
#检验用户输入是否为大写或小写y,输入为其他值时,脚本退出
#如果输入Y或y,再提示输入编辑类型。使用$EDITOR=""测试用户是否未赋值和未点击return键
#一种更有效的方法是使用-z $EDITOR方法
#如果测试失败,返回信息到屏幕,即使用vi做缺省编辑器,因而EDITOR赋值为vi
#如果用户输入了一个名字到变量EDITOR,则使用它作为编辑器并马上让其起作用,即导出变量EDITOR

18.3.19 检测最后命令状态

#前面将目录名传入脚本创建了一个目录,脚本然后提示用户是否应创建目录
#下面的例子创建一个目录,并从当前目录将所有*.txt文件拷入新目录
#但是这段脚本中用最后状态命令检测每一个脚本是否成功执行
#如果命令失败则通知用户$ pg ifmkdir2
#! /bin/bashDIR_NAME = testdirec
THERE = 'pwd'
mkdir $DIR_NAME > /dev/null 2>&1
if [ -d $DIR_NAME ];thencd $DIR_NAMEif [ $? = 0 ];thenHERE = 'pwd'cp $THERE/*.txt $HEREelseecho "Cannot cd to $DIR_NAME" >&2exit 1fi
elseecho "$cannot create directory $DIR_NAME" >&2exit 1
fi

18.3.20 增加和检测整数值

#脚本包含了一个计数集,用户将其赋予一个新值就可改变它
#脚本然后将当前值100加入一个新值
#用户输入一个新值改变其值,如果键入回车键,则不改变它,打印当前值,脚本退出
#如果用户用y或Y响应新值,将提示用户输入增量。如果键入回车键,原值仍未变。
#键入一个增量,首先测试是否为数字,如果是,加入计数COUNTOR中,最后显示新值$ pg ifcounter
#! /bin/bash
COUNTER=100
echo "Do you wish to change the counter value currently set at $COUNTER?[y..n]"
read ANS
if [ "$ANS" = "y" ] || [ "$ANS" = "Y" ];thenecho "Enter a sensible value"read VALUEexpr $VALUE + 10 > /dev/null 2>&1STATUS = $?if [ "$VALUE" = "" ] || [ "$STATUS" != "0" ];thenecho "You either entered nothing or a non-numeric" >&2echo "Sorry now exiting..counter stays at $COUNTER" >&2exit 1 fiCOUNTER = 'expr $COUNTER + $VALUE'echo "Counter now set to $COUNTER"
elseecho "Counter stays ai $COUNTER"
fi

18.3.21 简单的安全登录脚本

#以下是用户登录时启动应用前加入相应安全限制功能的基本框架
#首先提示输入用户名和密码,如果用户名和密码均匹配脚本中相应字符串,用户登录成功,否则用户退出
#脚本首先设置变量为假——总是假定用户输入错误,stty当前设置被保存,以便隐藏passwd域中字符,然后重新保存stty设置
#如果用户ID和密码正确(密码是mayday),明亮INVALID_USER和INVALID_PASSWD设置为no表示有效用户和密码,然后执行测试,如果两个变量其中之一为yes,缺省情况下,脚本退出用户
#键入有效的ID和密码,用户将允许进入。这是一种登录脚本的基本框架。
#下面的例子中有效用户ID为dave或pauline$ pg ifpass
#!/bin/bashINVALID_USER = yes
INVALID_PASSWD = yes
SAVEDSTTY = 'stty -g'
echo "You are logging into a sensitive area"
echo -n "Enter your ID name"
read NAME
stty -echo
echo "Enter your password:"
read PASSWORD
stty $SAVEDSTTY
if [ "$NAME" = "dave" ] || [ "$NAME" = "pauline" ];thenINVALID_USER=no
fiif [ "$PASSWORD" = "mayday" ];then
INVALID_PASSWD=no
fi
if [ "INVALID_USER" = "yes" -o "$INVALID_PASSWD" = "yes" ];thenecho "'basename $0 :' Sorry wrong password or userid"exit 1
fi
echo "correct user id and password given"

18.3.23 使用elif进行多条件检测

$ pg ifelif
#! /bin/bashecho -n "enter your login name:"
read NAME
if [ -z $NAME ] || [ "$NAME" = "" ];thenecho "You did not enter a name"
elif[ "$NAME" = "root" ];thenecho "Hello root"
elif[ $NAME = "louise" ];thenecho "Hello louise"
elif[ "$NAME" = "dave" ]
echo "Hello dave"
elseecho "You are not root or louise or dave but hi $NAME"
fi

18.3.24 多文件位置检测

#假定要定位一个用户登录文件
#已知次文件在/usr/opts/audit/logs或/usr/local/audit/logs中
#具体由其安装人决定
#在定位此文件前,首先确保文件可读,此即脚本测试部分
#如果为找到文件或文件不可读,则返回错误信息$ pg ifcataudit
#!/bin/bashLOCAT_1=/usr/opts/audit/logs/audit.log
LOCAT_2=/usr/local/audit/audit.logsif [ -r $LOCAT_1 ];thenecho "Using LOCAT_1"cat $LOCAT_1
elif[ -r $LOCAT_2 ]
thenecho "Using LOCAT_2"cat $LOCAT_2
elseecho "'basename $0':Sorry the audit file is not readable or cannot be located." >&2exit1
fi#运行上面脚本,如果文件在上述两个目录之一中并且可读,将可以找到它
#如果不是,返回错误并退出,下面结果失败,因为假象的文件并不存在

18.4 case语句

#case语句为多选择语句
#可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令
#case语句格式如下:
case 值 in
模式1)命令1...;;
模式2)命令2...;;
esac#取值后面必须为单词in,每一模式必须以右括号结束
#取值可以为变量或常数
#匹配发现取值符合某一模式后,其间所有命令开始执行直至;;
#取值将检测匹配的每一个模式
#一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式
#如果无一匹配模式,使用星号*捕获该值,再接受其他输入
#模式部分可能包括元字符,在与命令行文件扩展名例子中使用过的匹配模式类型相同
#即
* 任意字符
? 任意单字符
[..] 类或范围中任意字符

18.4.1 简单的case语句

#下面的脚本提示输入1到5
#输入数字传入case语句,变量ANS设置为case取值测试变量ANS,ANS将与每一模式进行比较
#如果匹配成功,则执行模式里面的命令直至;;
#这里只反馈非用户数字选择的信息,然后case退出,因为匹配已找到
#进程在case语句后仍可继续执行
#如果匹配为找到,则使用*模式捕获此情况,这里执行错误信息输出$ pg caseselect
#! /bin/bashecho -n "enter a number from 1 to 5"
read ANScase $ANS in1) echo "you select 1";;2) echo "you select 2";;3) echo "you select 3";;4) echo "you select 4";;5) echo "you select 5";;*) echo "'basename $0':This is not between 1 and 5" >$2exit 1;;
esac

18.4.2 对匹配模式使用|

#使用case时,也可以指定"|"符号作为或命令。例如vt100|vt102匹配模式vt100或vt102
#如果输入为vt100或vt102,将匹配模式'vt100|vt102',执行命令是设置TERM变量为vt100
#如果用户输入与模式部匹配,*用来捕获输入,其中命令将TERM设置为vt100
#最后在case语句外,导出TERM变量
#由于使用*模式匹配,无论用户输入什么,TERM都将有一个有效的终端类型值$ pg caseterm
#!/bin/bashecho "choices are.. vt100,vt102,vt220"
echo -n "enter your terminal type:"
read TERMINALcase $TERMINAL invt100|vt102) TERM=vt100;;vt220) TERM=vt220;;*) echo "'basename $0':Unknown response" >&2echo "setting it to vt100 anyway,so there"TERM=vt100;;esacexport TERM
echo "Your terminal is set to $TERM"

18.4.3 提示键入y或n

#case的一个有效用法是提示用户响应以决定是否继续进程
#如果用户输入Y、y或yes,处理继续执行case语句后面部分
#如果用户输入N、n或no或其他响应,用户退出脚本$ pg caseans
#!/bin/bashecho -n "Do you wish to proceed [y..n]"
read ANScase $ANS iny|Y|yes|Yes) echo "yes is selected";;n|N) echo "'basename $0': Unknown response" >&2exit 1;;esac

18.4.4 case与命令参数传递

#可以使用case控制到脚本的参数传递
#下面脚本中,测试特定变量$#,它包含传递的参数个数,如果不等于1,退出并显示可用信息
#然后case语句捕获下列参数:passwd、start、stop或help
#相对于每一种匹配模式执行进一步处理脚本$ pg caseparam
#!/bin/bashif [ $# != 1 ];thenecho "Usage:'basename $0'[ start|stop|help ]" >&2exit 1
fiOPT=$1case $OPT instart) echo "starting..'basename $0'";;stop) echo "stopping..'basename $0'";;help);;*) echo "Usage:'basename $0'[ start|stop|help ]";;esac

18.4.5 捕获输入并执行空命令

#如果要运行对应于一个会计部门的账目报表
#必须首先在决定运行报表的类型前确认用户输入一个有效的部门号,匹配所有可能值,其他值无效
#下面的脚本中如果用户输入部门不是234、453、655或454,用户退出并返回可用信息
#一旦响应了用户的有效部门号,脚本应用同样的计数取得报表类型
#在case语句末尾显示有效的部门号和报表类型$ pg casevalid
#!/bin/bashTYPE=""
echo -n "enter the account dept No::"
read ACCcase $ACC in234);;453);;655);;454);;*)echo "'basename $0': Unknown dept No:" >&2echo "try..234,453,655,454"exit 1;;esacecho "1.post"
echo "2.prior"
echo -n "enter the type of report:"
read ACC_TYPEcase $ACC_TYPE in1)TYPE=post;;2)TYPE=prior;;*) echo "'basename $0': Unknown account type." >&2exit 1;;esacecho "now running report for dept $ACC for the type $TYPE"

18.4.6 缺省变量值

#如果在读变量时输入回车键,不一定总是退出脚本
#可以先测试是否已设置了变量,如果未设置,可以设置该值
#下面的脚本中,要求用户输入运行报表日期
#如果用户输入回车键,则使用缺省日期星期六,并设置为变量when的取值
#如果用户输入另外一天,这一天对于case语句是运行的有效日期,即星期六、星期四、星期一$ pg caserep
#!/bin/bashecho "Weekly Report"
echo -n "What day do you want to run report [Saturday]:"read WHEN
echo "validating..${WHEN:="Saturday"}"case $WHEN inMonday|MONDAY|mon);;Sunday|SUNDAY|sun);;Saturday|SATURDAY|sat);;*) echo "Are you nuts!,this report can only be run on" >&2echo "on a Saturday,Sunday or Monday" >&2exit 1;;esac
echo "Report to run on $WHEN"#可以推出case语句有时与if then else语句功能相同
#在某些条件下,这种假定是正确的

18.5 for循环

for循环一般格式为:
for 变量名in列表
do命令1命令2...
done#当变量值在列表里,for循环即执行一次所有命令,使用变量名访问列表中取值
#命令可为任何有效的shell命令和语句
#变量名为任何单词
#in列表用法是可选的,如果不用它,for循环使用命令行的位置参数
#in列表可以包含替换、字符串和文件名

18.5.1 简单的for循环

#次例仅显示列表12345,用变量名访问列表
$ pg for_i
#!/bin/bashfor loop in 1 2 3 4 5
doecho $loop
done

18.5.2 打印字符串列表

#下面for循环中,列表包含字符串"orange red blue grey"
#命令为echo,变量名为loop,echo命令使用$loop反馈出列表中所有取值,直至列表为空$ pg forlist
#!/bin/bashfor loop in "orange red blue grey"
doecho $loop
done#也可以在循环体中结合使用变量名和字符串
echo "this is the fruit $loop"

18.5.3 对for循环使用ls命令

#这个循环执行ls命令,打印当前目录下所有文件$ pg forls
#!/bin/bashfor loop in 'ls'
doecho $loop
done

18.5.4 对for循环使用参数

#在for循环中省区in列表选项时,它将接受命令行位置参数作为参数
#实际上即指明:
for params in "$@"
或
for params in "$*"#下面的例子不使用in列表选项,for循环查看特定参数$@或$*,以从命令行中取得参数$ pg forparam2
#!/bin/bashfor params
doecho "You supplied $params as a command line option"
doneecho $params
done$forparam2 myfile1 myfile2 myfile3
You supplied myfile1 as a command line option
You supplied myfile2 as a command line option
You supplied myfile3 as a command line option#下面的脚本包含in"$@",结果与上面的脚本相同
$ pg forparam3
#!/bin/bashfor param3 in "$@"
doecho "You supplied $params as a command line option"
doneecho $params
done#对上述脚本采取进一步动作
#如果要查看一系列文件,可在for循环里使用find命令
#利用命令行参数,传递所有要查阅的文件$ pg forfind
#!/bin/bash
for loop
dofind / -name $loop -print
done#脚本执行时,从命令行参数中取值并使用find命令,这些取值形成-name选项的参数值
$ forfind passwd LPSO.AKSOP
/etc/passwd
/etc/pam.d/passwd
/etc/uucp/passwd
/usr/bin/passwd
/usr/local/accounts/LPSP.AKSOP

18.5.5 使用for循环连接服务器

#因为for循环可以处理列表中的取值,现设变量为网络服务其名称,并使用for循环连接每一服务器
$ pg forping
#!/bin/bashHOSTS="itserv dnssevr acctsmain ladpd ladware"
for loop in $HOSTS
doping -c 2 $loop
done

18.5.7 多文件转换

#匹配所有以LPSO开头文件并将其转换为大写
#ls用于查询出相关文件,cat用于将之管道输出至tr命令
#目标文件扩展名为.UC,注意在for循环中使用ls命令时反引号的用法$ pg forUC
#!/bin/bashfor files in `ls LPSO*`
docat $files | tr "[a-z]" "[A-Z]" >files.UC
done

18.5.8 多sed删除操作

#sed用于删除所有空文件,并将输出导至以.HOLD.mv为扩展名的新文件中,mv将这些文件移至初始文件中
#!/bin/bashfor files in `ls LPSO*`
dosed -e "/^$/d" $files >$files.HOLDmv $files.HOLD $files
done

18.5.9 循环计数

#前面讨论expr时指出,循环时如果要加入计数,使用此命令
#下面使用ls在for循环中列出文件及其数目$ pg forcount
#!/bin/bashcounter=0
for files in *
docounter = `expr $counter + 1`
doneecho "There are $counter files in 'pwd' we need to process"#使用wc命令可得相同结果
$ ls | wc -1

18.5.10 for循环和本地文档

#在for循环体中可使用任意命令
#一个变量包含所有当前登录用户
#使用who命令并结合awk语言可实现此功能
#然后for循环循环每一用户,给其发送一个邮件,邮件信息部分用一个本地文档完成$ pg formailit
#!/bin/bashWHOS_ON = `who -u | awk '{print $1}'`
for user in $WHOS_ON
do
mail $user << MAYDAY
Dear Colleagues,
It's my birthday today,see you down the club at 17:30 for a dring.see ya.
$LOGNAME
MAYDAY
Done

18.5.11 for循环嵌入

#嵌入循环可以将一个for循环嵌在另一个for循环内:
for 变量名1 in 列表1
dofor 变量名2 in 列表2do命令1...done
done#下面脚本即为嵌入for循环,这里有两个列表APPS和SCRIPTS
#第一个包含服务器上应用的路径,第二个为运行在每个应用上的管理脚本
#对列表APPS上的每一个应用,列表SCRIPTS里的脚本将被运行,脚本实际上为后台运行
#脚本使用tee命令在登录文件上放一条目,因此输出到屏幕的同时也输出到一个文件
#查看输出结果就可以看出嵌入for循环怎样使用列表SCRIPTS以执行列表APPS上的处理$ pg audit_run
#!/bin/bashAPPS="/apps/accts /apps/claims /apps/stock /apps/serv"
SCRIPTS="audit.check report.run cleanup"
LOGFILE=audit.log
MY_DATE=`date +%H:%M` on `%d%m%Y`for loop in $APPS
do
for loop2 in %SCRIPTS
doecho "system $loop now running $loop2 at $MY_DATE" | tee -a $LOGFILE$loop $loop2 &done
done

Linux-Shell(六)相关推荐

  1. Linux Shell脚本入门教程系列之(十六) Shell输入输出重定向

    本文是Linux Shell系列教程的第(十六)篇,更多Linux Shell教程请看:Linux Shell系列教程 Shell中的输出和输入的重定向是在使用中经常用到的一个功能,非常实用,今天就为 ...

  2. Linux Shell脚本入门教程系列之(六)Shell数组

    本文是Linux Shell脚本系列教程的第(六)篇,更多shell教程请看:Linux Shell脚本系列教程 Shell在编程方面非常强大,其数组功能也非常的完善,继上一篇之后,今天就为大家介绍下 ...

  3. 执行远程linux命令,linux shell 远程执行命令

    经常要部署多台服务器上面的应用,如果一个个机器的登录太麻烦. 所有就想到编写一个脚本来部署不同的服务器 前提条件: 配置ssh免登陆 如果不会的请参加我的另外一篇文章 http://blog.csdn ...

  4. Linux Shell高级技巧(目录)

    为了方便我们每个人的学习,这里将给出Linux Shell高级技巧五篇系列博客的目录以供大家在需要时参阅和查找. Linux Shell高级技巧(一)  http://www.cnblogs.com/ ...

  5. linux中的shell有printf吗,Linux Shell系列教程之(八)Shell printf命令详解

    在上一篇:Linux Shell系列教程之(七)Shell输出这篇文章中,已经对Shell printf命令有了一个简略的介绍,本篇给大家详细介绍下Shell中的printf命令. 一.Shell p ...

  6. Linux Shell常用技巧(目录)

    Linux Shell常用技巧(一) http://liuxuyang.blog.51cto.com/2546552/1289413 一. 特殊文件: /dev/null和/dev/tty 二. 简单 ...

  7. 【shell 大系】Linux Shell常用技巧

    在最近的日常工作中由于经常会和Linux服务器打交道,如Oracle性能优化.我们数据采集服务器的资源利用率监控,以及Debug服务器代码并解决其效率和稳定性等问题.因此这段时间总结的有关Linux ...

  8. linux shell脚本字符串连接符,学习Linux shell脚本中连接字符串的方法

    这篇文章主要介绍了Linux shell脚本中连接字符串的方法,如果想要在变量后面添加一个字符,可以用一下方法: 代码如下: $value1=home $value2=${value1}"= ...

  9. shell的建立与执行实验报告_实验指导书--实验02 Linux Shell用户接口

    实验二:Linux Shell用户接口 实验学时:2 实验类型:验证 实验要求:必修 一.实验目的 通过本实验的学习,使学生掌握Linux Shell的使用方法. 二.实验内容 实验内容:实践Linu ...

  10. Linux Shell常用技巧(七)

    十六. 文件查找命令find: 下面给出find命令的主要应用示例:     /> ls -l     #列出当前目录下所包含的测试文件     -rw-r--r--. 1 root root ...

最新文章

  1. Ubuntu开机后一直循环登录,却进不去桌面
  2. Qt程序运行提示“it could not find or load the QT platform plugin “windows””
  3. OSI模型中的数据链路层和物理层的区分
  4. 2020最详细安装Ubuntu指南
  5. multi task训练torch_采用single task模型蒸馏到Multi-Task Networks
  6. vue中获取输入框中得到值_如何获取vue input的值
  7. 图片生成html_markdown 生成头条文章的一个实现
  8. jsp实验管理系统开题报告_MR教育燧光与广东实验中学关于MR化学课程开题报告研讨会顺利完成...
  9. EXCEL 数据透视表的简单使用
  10. CentOS 7 GNOME经典桌面 拼音输入法设置
  11. Python 基础语法
  12. 这四种加薪理由,肯定没戏!
  13. pandas读取xls文件
  14. 罗技无法使用计算机上的配置文件,罗技无线鼠标接收器无法配对的详细解决办法...
  15. 工作15年码农总结:学编程难吗?那只是你觉得难!
  16. 知乎上的100条简短深刻的回答
  17. 右手螺旋判断磁感应强度方向_高中物理电流磁场的判断方法是什么?叉乘方向右手螺旋定则如何运用...
  18. 各个协议层的网络请求
  19. 【微软漏洞分析】MS15-023 Win32k 特权提升漏洞 - CVE-2015-0078 + 绕过(CVE-2015-2527 in MS15-097)
  20. 基于微信小程序的短视频系统#毕业设计

热门文章

  1. vue笔记1 渐进式、 MVVM 框架
  2. Python基础篇5:输入两个数,求它们的和、差、积、商、余数
  3. Visual Studio 实用插件推荐
  4. 基于SPI协议的Flash驱动控制-扇区擦除
  5. 如何更改计算机c盘中用户名,windows10家庭版怎么更改c盘中的用户名_win10家庭版修改c盘用户名操作方法...
  6. 大数据毕设 地铁客流分析与可视化系统
  7. 用AI生成的画作,在淘宝拍卖到了4位数
  8. SCI论文编辑教你如何准备SCI论文和写作 [转]
  9. 电子签名行业2017新风向
  10. sparkSQL操作中spark内报错“拒绝连接”解决方案