shell----编程实例.doc_第1页
shell----编程实例.doc_第2页
shell----编程实例.doc_第3页
shell----编程实例.doc_第4页
shell----编程实例.doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1. 判断一个文件是否是 可执行文件,且判断能否在PATH中找到,有三种结果 (一)找到且可执行 0 (二)非情况一 (2)没找到或者是不可执行 1 (3)没找到 2函数in_path:判断传入文件是否可执行,若可执行(且存在)返回0, 否则返回1;分析:为测试传入文件是否在PATH所有的目录中,需取得PATH中的每个路径,可用循环,但需要设定环境中的分隔符(借助环境变量IFS)为 PATH中的分隔符冒号”:” 注:$IFS 输入分隔符. 当shell读取输入数据的时候,会把一组字符看做是单词之间的分隔字符,它们通常是空格,制表符,和换行符.函数调用方式为 : in_path filenamein_path()cmd=$1 # $1为函数的参数1,以此类推retval=1 #定义返回值变量oldIFS=$IFSIFS=:#设置新的IFS,并保存原来的以恢复使用for directory in $PATH #for循环结构二: for indoif -x directory/$cmd ; then #if条件语句之 同行表示 以分号隔开retval=0 # -x 判断文件有是否有可执行权限donedoneIFS=$oldIFS #恢复原来IFS, return retval注:1.函数的结构, 没有形参2.变量的引用需要符号$,而变量的定义或赋值则不需要。3.赋值要无间隙, 条件要间隙改进: 1.将路径、分隔符均作为函数的参数传入,应用得到扩展。补充,in_path函数不能对绝对路径的文件处理,需写个函数对这一情况单独处理checkForCmdInPath()var=$1#首先判断传入的非空串是否为绝对路径,即检测第一个字符是不是”/”,如果是,直接测 x if $var != “” ; then # 条件等价于 -n $varif “$var%$var#?” = / ; then #等价于 $(echo $var | cut -c1) if ! -x $var ; thenreturn 1 #not found or not executable fielif ! inpath $var ; then return 2 #not found in PATHfifi注:此函数让人一头雾水,详解如下:1) 表达式$var%$var#?作匹配用,分解为 $var%expr $var#expr ,expr为正则表达式(? 匹配单一字符) 后者(带#的)返回 expr与var匹配成功位置之后的所有内容,此处为var中第一字符之后的所有。 前者(带%的)返回 expr与var匹配成功位置之前的所有内容,此处应为 var的第一个字符。 等价于 $(echo $var | cut c1) 即取第一字符。等价于 $var:beginpos:size 中beginpos=0,size=1时的结果。 var的符号放在外面了,假设$var为$1,则表达式表示为 $1%$1#?2) 关于if的条件判断与C语言中的理解不一致,反映在上述的 elif语句中的条件。理解如下:shell中的if条件可以是 表达式(需加方括号),另外还可以是命令或函数(不需方括号), 当命令执行成功时会后继执行具体操作,经测试,C语言中所说的true在shell中 用0表示,即if 0,才执行then,因为linux下的程序实现都是当返回0时表执行成功。3) 若函数中没有返回值,则它默认返回0,表执行成功。 函数的编写若遵从以上的原则, 则对条件的理解 依旧像C语言中的TRUE,FALSE一样理解= 完善程序代码 =#!/bin/bashin_path(). # 函数实现区域 处理不路径 返回0表找到、可执行, 否则返回1#checkForCmdInPath(). # 函数实现区域 处理带路径和不带路径的 返回1表没找到或不可执行,返回2表没找到。默认0表找到 # # 代码执行起始位置 # if $# -nq 1 ; thenecho “Usage: $0 command” #$0 表此执行文件 (具体内容 以 执行此文件时的输入串为准)exit 0 fi# 调用函数,并经第一个参数传给函数checkForCmdInpath $1# 对函数返回的结果进行判断 $? 为函数的返回值,case $? in # case 控制结构的格式,注意红色部分。0)echo “found in PATH”;1)echo “not found or not executable”;2)echo “not found”; # *) ; 类似于C语言中的 default=2.写一个脚本,检测用户输入串的合法性, 要求串由大小写字母、数字组成,无标点、特殊符号、空格。思路:将输入的串中 非字母数字的内容删除或替换为空后若和原来输入的相同则合法,否则不合法。isvalidAlphaNum()compressed=”$(echo $1 | sed s/:alnum:/g)” #替换不合要求字符为空if “$compressed” != “$1” ; thenreturn 1# not valideelsereturn 0 # validefi注: 1.关于引用变量时是否需要双引号的说明 如果只是输出,可以不用双引号 如果变量值代的内容中无空格,表达,特殊符号,在引用时可以不需要双引号,反之,最好带双引号,否则在变量处理时很有可能会出现“参数过多”等莫名其妙的错误信息。 2.关于匹配处理,sed是单行编辑程序。 sed s/str1/str2/g file 将文件file中每行内str1替换为str2 :alnum:表示所有字母和数字中的任一个字符。若只是:alnum:则表示 方括号中的任一个字符。 :alnum: 表除了所有字母数字外的任一字符。如果是直接向脚本传字符串,则带空格的字串会被脚本自行分解为多个参数,所以可采用从标准输入读取的方式获得字串。= 完善程序代码 =#!/bin/bashisvalidAlphaNum() . #函数体,判断字串的合法性echo -n “Enter input:”# -n 强制不换行read input#读取内容存到input中, 无 $ 符号if ! isvalidAlphaNum “&input” ; then #加引号,否则可能会出错。echo “invalide”exit 1elseecho “valide”fiexit 0=3输入一个 “month day year”格式的日期串,程序将处理” month”为 其英文单词的前三个字母,第一个字母大写,其余的小写。思路:首先判断month是数字、还是单词,若是数字,则可查“数字month”映射表(自定义case结构);若是单词,则取前三个字母,并格式化。函数monthnoToName() 将month数字转换为month名monthnoToName() case $1 in 1 ) month=Jan ; 2 ) month=Feb ; 3 ) month=Mar ; 4 ) month=Apr ; 5 ) month=May ; 6 ) month=Jun ; 7 ) month=Jul ; 8 ) month=Aug ; 9 ) month=Sep ; 10) month=Oct ; 11) month=Nov ; 12) month=Dec ; * ) echo $0: Unknown numeric month value $1 &2; exit 1 # default, esac# return 0假设通过传三个参数到脚本month day year- 实现代码 -#!/bin/bashif $# -ne 3 ; then #若参数个数不为3,则有误echo “Usage: $0 month day year”exit 1fi#判断参数1是数字还是单词,方法 替换串中所有数字,若结果为空,则为数字,否则为单词。if -n $(echo $1 | sed s/:digit:/g) # -n 检测串是为空thenmonthnoToName $1# 数字else# 取第一个字母并将其变为大写,再将结果与取出的第二三字母组合month=”$(echo $1 | cut c1 | tr :lower: :upper:)“month=”$month$(echo $1 | cut -c2-3 | tr :upper: :lower:)”fiecho $month $2 $3 # 输出结果exit 0-注:1.外围可以使用函数中定义的变量,如函数monthnoToName中定义的month变量,最后echo会用到它。2. 多管道(|)的使用3. month变量的合并, $var$var4. tr SET1 SET2 转换/删除/替换 命令, 将默认 将SET1 替换为 SET2 tr 默认从标准输入读取,处理后 写入 标准输出。5. cut c2-3 file取文件每行第2,3字母。扩展: 处理MM/DD/YYYY or MM-DD-YYYY 的形式。在判断三个参数前执行命令set - $(echo $1 | sed s/-/ /g) 。set 的 - 命令可以将其后的参数赋予 位置参数($1,$2,.) 。 链接 set 指令 用法4. 格式化输出 大数字,使输出结果更容易让人知道该输出数字的数量级。默认用逗号分隔整数部分,用点号分隔整数与小数部分,当然用户也可以使用 d 指定整数的分隔符,用-t指定整数与小数部分的分隔符。算法: 1232342142.423023 = 默认:1,232,342,142.423023(1)首先分开整数部分integer 和小数部分decimal, sed d. -f1 和 sed d. -f2 分别取两部分。(2)整数部分的处理: 当作数字来处理 %运算 /运算1)每次取整数低三位,长度小于3就补前缀0(避免出现漏0情况,例如低三位为003时,取后便为值3)2)将此次得到的三位与上一次得到的三位用分隔符(如果没有指定就默认)组合起来。3)整数去掉低三位,继续操作1)。当此整数小于等于999就不再继续。 当字串来处理:1)每次取低三位, cut c $($#str - 2)-$#str $#str 为str的长度,必须为大括号。$( ) 的内部为str长度-2,代表倒数低三个字符。因为内部是减法,所有此为双小括号。2)原串每次都要裁掉尾部三个字符,每次取到的字串的长度为循环判断条件。函数 nicenumber()作如上处理nicenumber()# 传入 integer.decimal 如2000023.2, 32232332等# 分别取 整数部分和小数部分integer=$(echo $1 | cut d. f1)decimal=$(echo $1 ! cut d. f2)# 判断小数部分是否存在,因为这涉及连接整数和小数的连接符问题# 设DD 为 整数和小数之间分隔符,默认为 .if n $decimal ; then#若非空,即有小数部分。#以下四句可用一句表示:result=”$DD:=”.”$remainder$result”if -z $DD ; then #判断用户是否自定义整数与分隔符,若空DD=.firesult=$DD$decimal # 在小数部分前加 分隔符。fithousand=$integerwhile thousand gt 999 doremainder=$(thousand%1000)while $#remainder lt 3 ;do#$#remainder 为remainder串的长度remainder=0$remainder# 避免remainder为00x时的丢0情况。donethousand=$($thousand/1000)#以下四句可用一句表示:result=”$TD:=”,”$remainder$result”# 上面蓝色部分表:若TD非空则返回TD,否则将”,”赋给TD.if z $TD ; then# 判断用户是否自定义整数分隔符, 若 空TD=,firesult=”$TD$remainder$result”# 与分隔符合成串。 注意顺序doneif n $thousand ; then# 若 非空result=”$thousand$result”elif $result%$result#? = “$TD” ; thenresult=”$result#?”fiecho $result脚本标志参数处理命令: getopts “” var带两个参数,第一个参数为带解析的 参数标志序列串(如-f,-c等), 以冒号(:)分隔各标志,且以冒号:结束第二个参数为:变量,每执行一次存放 参数标志序列串中的一个标志字符返回值:未解析结束返回0,解析结束返回1涉及的内定变量:$OPTARG 每次解析标志对应的参数值 便默认存放在此变量内。$OPTIND当各标志处理无误情况下,该数值指示当前用到的最大位置参数($#)。 此值使用容易出错(若参数的判断不完善时), 还不如用 $#另外 $1, $2, $3, $4, = 此时 $# 等于 4,当执行shift 1 时, 各个位置参数的值向一次向左右1次,此时 $1的值 为原$2的值当执行shift 2 时, 各个位置参数的值向一次向左右2次,此时 $1的值 为原$3的值。完整代码 - nicenumber.sh -nicenumber(). # 函数实现部分#处理脚本标志参数while getopts “d:t:” optdocase $opt in# $opt 为 具体的标志字符d ) DD=”$OPTARG”;# $OPTARG 为标志指定的参数值t ) TD=”$OPTARG”;* ) echo “no arg-flag: $opt” &2;exit 1esacdone# 当脚本接收如此多的参数时,$1将不代表脚本最终要处理的大数字,所以做如下操作。shift $($OPTIND - 1) nicenumber $1exit 0-扩展:1.不同国家整数与小数的分隔符不同,使脚本能够处理各种整数与小数各种分隔符情况。在传给脚本参数时需指定标志-d程序中仅需在 分隔 整数与小数部分略修改为integer=$(echo $1 | cut “d$DD:=”.” f1 )decimal=$(echo $1 | cut “d$DD” f2 )2.另外,可以在程序执行之前分别初始化DD,TD默认值。3. 检测传给脚本的大数值中是否含有 非法的整小数分隔符,即存在与用户指定或默认分隔符不同的符号。 方法:删除其中所有数字,看剩下的内容,若不空且不等于$DD,则非法separator=”$(echo $1 | sed s/:digit:/g)”if -n $separator & “$separator” != “$DD” ;then # 蓝色部分可用 a 表示exit 1fi5. 检测 输入整数的合法性,可负数(-1, -2均合法), 可以指定传入整数范围,不在范围内则报错。参数:1或3个, 当3个时,后两个为范围。合法性:正负数的判断,范围的判断。validint()integer=$1min=$2max=$3# 判断传参的合法性,以下判断是错误的,因为不管参数是否为空,实际上都传了三个参数。if $# -eq 0 ;then # 改成判断$1的内容是否为空,就可以了echo “you couldnt do nothing”&2return 1fi#判断是否为负数,第一个字符 是否为 , 如是,则判断后面的是否为整数。若非负,则判断是否为整数if “$(echo $1 | cut c1)” = “-” ; thensigned=”-”integer=”$integer#?”fi# 如果就是一个符号 -,则也是非法的if -z “$integer” ; thenecho “Invalid input, just a “-” is not allowed”&2 #注意:&2 三个字符紧连。return 1fi# 如果非纯数字构成,则非法。if -n “$(echo $integer | sed s/:digit:/g)” ; thenecho “Invalid integer, it includes some char but digit”&2return 1fiinteger=”$signed$integer”# 范围判断,注意当 min 和 max 为空时(即未传范围),我设定其为$integer,如此判断就不会出错。if $integer lt $min:=$ingeger ;thenecho “$integer is too small, it should greater than $min”&2return 1fiif $integer gt $max:=$integer ;thenecho “$integer is too large, it should little than $max”&2return 1fireturn 0-执行代码-#!/bin/bashvalidint().#if validint “$1”“$2” “$3”; thenecho “your input is valide”fi注:if ! -z $min -a $number -lt $min 为AND表达式,但在shall脚本中,当第一个条件为false时,不能保证第二个条件不被测。 而将if条件改写成两层嵌套的if语句后,当第一个为false时,则第二个一个不会被测。6. 检测浮点数的合法性。参数:1个浮点数 合法性: 不支持科学表示法,支持带符号 -1.2 -.75均合法。思路:首先要判断是整数还是浮点数,只是一种可能性的判断,即判断有没有 点有点的情况:依据“.”劈成两半,前半为合法整数。后半必须为 =0 的整数。需调用上一例中的判断整数合法性的validint()函数无点的情况:基本做整数判断处理函数: validfloat()fvalue=$1# 保证传入参数非空if -z “$fvalue” ; thenecho “you input nothing”&2return 1fi# 判断有点否?(清除点以外的字符,看看结果是否为空)if -n $(echo $fvalue | sed s/./g) ; theninteger=”$(echo $fvalue | cut d. f1 )”decimal=”$(echo $fvalue | cut d. f2 )”/判断整数部分的合法性,当仅为 时,把它看成0,免去判断if “$integer” != “-” ; thenif ! validint “$integer” ; thenecho “part before dot $integer is not valide!”&2return 1fifi/判断小数部分整数的合法性。必须=0, 当为空时不判断。if -n “$decimal” ; thenif ! validint “$decimal” 0 ; thenecho “part after dot $decimal is not valide!”&2return 1fifi else# 没有点,就当作整数处理if validint “fvalue” ; thenecho “your input is a integer”&2return 1fifi-完整代码 validfloat -#!/bin/bash. validint#引用别的文件定义的函数。validfloat(). # 实现部分if validfloat $1 ; thenecho “$1 is a valid floating-point value”fiexit 0-7. 检测日期的合法性1) 参数形式 “month day year” 见例3。2) day的合法性。 day 与 month的关系 case-in 函数1闰年:能被4 和400整除为闰年。 若能被4但不能被400整除,若被能被100整除则为闰年. 函数23) 输出 month day year, 其中month为单词的前三个字母,第一个大写,其余小写。涉及的重点;1 case-in结构: case $1 in jan* ) days=31 ; / 可以串(不同于C),且可以用通配符。2. if $2 -lt 1 -o $2 -gt $days ; then/ -o 或语句3. 整除的判断 运算符% 取模4. 获取脚本或函数的参数列表$* : 将参数列表合成了一个一个以IFS分隔的串, 形如: “arg1 arg2 arg2”$ : 指代参数列表,形如 : “arg1” “arg2” “arg3”将两者传给函数或脚本后,$#的值不同,但传入参数列表的打印结果(即 echo $*)一样8. 模拟echo,实现最简单的硬输出,即脚本后面有什么参数就输出什么,且不会自动加换行符。例如:./echon “just a test1” ; ./echon n “test2“结果: just a test1-n test2luokuimachine$ 思路:将脚本接收的参数作为一个串(”*”)处理,并去掉尾部可能存在的换行符(n) 具体实现:方法一: echo n “$*” 可将脚本的-n参数,输出脚本参数,强制不换行方法二: 格式化输出命令printf, printf “%s” “$*” (格式串无换行) 方法三: 转换/删除命令tr , echo “$*” | tr d n , -d 删除字符集中的字符。方法四: 模式-命令指令 awk, echo “$*” | awk printf “%s” $09. $()符号内可进行基本的运算,但是其内部参与运算的以及其得到的结果都是整数,即无浮点精确表示。本例处理浮点运算,可以指定精确度,通过对命令bc进行包装。 bc 处理的是一种类似C的语言,其处理文件,或键入bc直接进入bc程序,从stdin接收数据。但是刚运行bc时会出现bc的版权等信息。写个脚本进行包装,并可以接受运算表达式且可指定精度。 -q flag 允许为bc指定精确度。 quit 为退出bc的语句。脚本用到 “here document”的非常有用的功能, bc q EOF .EOF10. 锁定文件、安全共享。1) lockfile l u r num file-l : lock 操作-u: unlock 操作-r: 指定尝试次数num2) “here document”的应用cat &2.EOF3) 分析如下代码做“锁定文件”的效果while -f $lockfile ; do sleep 1donetouch $lockfile分析:没有效果,在done和投产之间很可能会被其它进程投机lockfile doesnt work with NFS-mounted disks.lockfile的具体使用方法:待了解11. 格式化 ANSI 终端颜色定义、字体格式esc=”033” # 或者直接按ESC键格式代码如下:“$esc m” 红色下划线部分为某数字,该变量指定了其修饰的文本颜色或字体格式。例:redf=”$esc31m”代表 红色前景色echo “$redfThis is a red-color line”常用格式数字:前景: 黑、红、绿、黄、蓝、紫、青、白30-37背景:.40-47boldon : 1 ; boldoff : 22 加粗开关italon: 3 ; italoff : 23斜体开关ulon: 4;uloff:24下划线开关reste: 0重设,恢复原始12. 创建shell脚本库创建一个脚本library.sh,里面仅包含函数,当其它脚本需要用到此脚本中的函数时,需用符号” . “ 包含library.sh,在没有“.”符号情况下包含另一个脚本文件时,当被包含脚本执行时,不会影响调用它的脚本的运行环境,13.调试shell脚本echo打印文件中的某行 sed n nump file$: 当前的进程id14. 格式化文本 行宽度、连接符等fmt / nroff 1. “here document”的应用nroff 正则表达式_学习 正则表达式30分钟入门教程.doc 旧)。do#依据文件名$name获得,组合出删除时间。 datetime=$(echo $name | cut -c1-14| #获得文件名中的时间串1-14个字符 awk -F. print $5/$4 at $3:$2:$1 ) #-F 指定串的分隔符,awk打印格式串。若$name是目录(-d) ,计算其下的文件数size=”$(ls $name | wc l | sed s/:digit:/g)”若$name是文件(-f), 计算文件的大小size=”$(ls sdkl $name | awk print $1)” # ls sdkl file 第一列会显示文件file的大小(以K计,-k),当不加file时,结果很意外。打印文件的信息done#上面列出了重名的文件的信息,接下来要用户选择具体的操作。read desired#读取用户想要进行的操作项号若大于重名数,则太大,退出若小于1,则太小,退出。若目的目录中是否存在$1名字相同的文件(-e),若存在,则不能覆盖,退出根据用户的输入操作好,获得待恢复文件的文件名(含时间)restore=$(ls -td *$1 | sed -n $desiredp) #此处ls要使用与上面循环是的排序方式一致, sed 部分p命令打印第 用户输入的号desired行。恢复文件mv restore dest/$1#注意当前工作目录询问用户是否删除其它重名的文件read answeryes:rm f *”$1”no : exit 0等于1时,即无重名,先判断目的目录下是否已存在待恢复文件名(-e),如有,则退出,否则恢复文件另外,程序中执行指令时,若出错,则可能会有错误信息,为避免这种情况,对于可能出错的命令进行进行重定向到/dev/null,抛弃错误信息。17. 调用该脚本删除文件时,会将删除记录在log文件中。1) USAGE: logrm.sh -s 文件列表/目录2)-s 带此参数时会,删除结果不记录在文件中。3) shift命令(有-s时会用到)会影响 “$”或”$*”的值4) 应当删除成功再记录log,文件列表前可以带些rm的参数标志,但必须在-s(如果有的话)之后5) 日志格式:echo “$(date): $(USER): $” rmlog18. 定制ls,按特有的格式显示目录的内容1.usage: formatdir.sh dirname2.每行只有两列,每列的格式 : filename (size) 或 dirname (entries),具体如下:Size 又分 Kb/Mb/Gb, entries即 目录下的实体(文件及目录不递归)数3. 思路:判断目录下的每一项是文件还是目录若文件,则先(ls sk file | awk print “$1”)获得该文件大小,并选择适当的单位(Kb/Mb/Gb)表示。若目录,则计算其下的项数: ls l dirname | wc l | sed s/:digit:/g若为1, 则小括号中显示 entry若大于1,则小括号中显示 entries格式化输出:每行两列,BASH shell set命令详解使用set命令可以设置各种shell选项或者列出shell变量.单个选项设置常用的特性.在某些选项之后-o参数将特殊特性打开.在某些选项之后使用+o参数将关闭某些特性,不带任何参数的set命令将显示shell的全部变量.除非遇到非法的选项,否则set总是返回ture.当BASH shell被调用时,可以列出全部的选项.当前的选项集列在$-中.在option参数被处理后,其他的参数被赋值到位置参数中($1,$2,.,$n)set -abefhkmnptuvxldC

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论