Linux程序设计之shell
2014-07-11 14:51
134 查看
一、Shell简介
Shell是一个作为用户与linux操作系统之间的接口的程序,它允许用户向操作系统输入需要执行的命令。Shell执行shell程序,这些程序通常称为脚本,它们是运行时解释执行的。
版本查询:/bin/bash–version
历史版本
sh(Bournce) 源于UNIX早期版本的最初的shell csh、tcsh、zsh C shell及其变体,是继bash和Korn shell之后的第三个最流行的sehll ksh、pdksh Korn shell和它的公共域兄弟pdksh由David Korn编写,是许多商业版本UNIX的默认shell bash 来自GNU项目的Bourne Again Shell是linux主要的shell。优点是可以免费获取其源代码,即使没有运行它,它可能已经移植到系统中注:大多数linux发行系统中,默认的shell程序/bin/sh实际上是/对程序bin/bash的一个连接
二、Shell Script简介
Shell script是利用shell的功能所写的一个程序,它是使用纯文本文件,将一些shell的语法与命令写在里面,搭配正则表达式、管道命令和数据重定向等功能,已达到我们的目的。Shell script用在系统管理上面是很好的一项工具,但是用在处理大量数值运算上,就不够好了。因为shell script的速度较慢,且使用的cpu资源较多,造成主机资源的分配不良。
Shell script优点
1、自动化管理的依据。例如系统每天都会自动查询登陆文件、追踪流量、监控用户主机状态、各项硬件设备状态等工作,都是通过脚本自动执行的。
2、追踪和管理系统的重要工作。例如,我们想重新启动系统注册表文件,可以使用“/etc/init.d/syslogd restart”,syslogd就是script。
3、简单入侵检测功能。
4、连续命令的单一化。例如需要执行很多相似的命令,就可以使用script实现。
5、简单的数据处理。例如使用awk可以对数据进行处理
6、跨平台支持与学习历程较短。因为几乎所有的UNIX系统都会使用shell script。
缺点:虽然shell script号称是程序,但是处理数据的速度上是不够的,因为shell script用的是外部命令与bash shell的一些默认工具,所以,它经常会调用外部函数库,因此周期长。
三、Shell 编程语法
1、变量
在shell里面,变量通常并不需要事先声明,只是通过使用它们来创建它们。默认情况下,所有变量都被看作字符串并以字符串来存储,即使被赋值为数值时也是如此。在shell中,可通过在变量前面加一个$符号来访问它的内容。增加变量内容,使用“$var”或者${var}
注:如果字符串里包含空格,就必须用引号把它们括起来。此外,等号两边都不能有空格。因此字符串通常都被放在双引号中,以防止变量被空白符分开,同时允许$拓展。
(1) 使用引号
将$变量表达式放在双引号中,程序自动替换引号中变量的值,如果放在单引号 中,不会发生替换现象。
(2)环境变量
主要的环境变量(自定义变量=局部变量 系统变量=全局变量)
$HOME 当前用户的家目录 $PATH 以冒号分隔的用来搜索命令的目录列表 $PS1 命令提示符,通常是$字符。 $PS2 二级提示符,用于提示后续的输入,通常是>字符 $IFS 输入域分隔符。Shell输入时用它来分隔字符,通常是空格、制表符或换行符 $0 Shell脚本的名称 $# 传递个脚本的参数个数 $$ Shell脚本的进程号,通常用它生成唯一的临时文件 ? 上一个任务的回传码 export 自定义变量转成环境变量
(3)参数变量
$1,$2….. | 脚本程序的参数 |
$* | 在一个变量中列出所有的参数,各个参数之间用IFS分隔开。若IFS被修改,则$*将命令行分隔为参数的方式将随之改变。 |
$@ | $*的变体,不适用IFS |
(4)变量的读取
变量键盘读取、数组与声明:read、array、declare
Read:读取来自键盘输入的变量 参数 –p(后面接提示符) -t(等待时间)
Array: echo “${var[1]}” “${var[2]}”
Declare/typeset: 声明变量的类型
2、布尔判断命令[或test
test -f file 等价于 [ -f file ]
注:使用[]时每个组件之间都需要空格来分隔,中括号里面的变量最好使用“”括起来,常量最好都以‘‘或“”括起来。
条件类型:
string 1 = string2 如果两个字符串相同则结果为真 string 1 != string2 如果两个字符串不相等则为真 -n string 字符串不为空则为真 -z string 字符串为空则文件条件测试:
-d file 判断文件名是否存在且为目录 -e file 判断文件名是否存在 -f file 判断文件名是否存在且为文件 -g file 判断文件名是否存在且具有“SGID”的属性 -u file 判断文件名是否存在且具有“SUID”的属性 -r file 判断文件名是否存在且具有“可读”的权限 -x file 判断文件名是否存在且具有“可执行”的权限 -w file 判断文件名是否存在且具有“可写”的权限 -s file 判断文件名是否存在且为“非空白文件” -p file 判断文件名是否存在且为一个FIFO(pipe)文件 -b file 判断文件名是否存在且为一个block device设备 -c file 判断文件名是否存在且为一个character device设备 -L file 判断文件名是否存在且为一个连接文件算术比较:
expression1 -eq expression2 两个表达式相等则为真 expression1 -ne expression2 两个表达式不相等则为真 expression1 -gt expression2 expression1大于expression2为真 expression1 -ge expression2 expression1大于等于 expression2为真 expression1 -lt expression2 expression1小于 expression2为真 expression1 -le expression2 expression1小于等于 expression2为真 ! expression 表达式为假则结果为真多重条件判断,例如test -r filename -a -x filename
-a 两个条件同时满足 -o 两个条件满足任意一个 ! 反向状态3、控制结构
(1)if语句
格式:
if condatation if condtaion then then statements statements ====== elif elif statements statements else else statements statements fi fi
例: if [ -f file ]; then
(2)for语句
格式:
for variable in values do statements done
注:使用通配符可以拓展语句
例如:循环从1加到100 for variable in $ ( seq 1 100 );
(3)while语句
格式:
while condation do statements done
(4)until语句
格式:
until condaion do statements done
(5)case 语句
格式:
case variable in pattern [ | pattern ] …) statements;; pattern [ | pattern ] …) statements;; ….. esac
(6)命令列表
AND列表:statement1 && statements2 && statements3 && …. OR 列表:statements1 || statements2 || statements3 || …
(7)语句块
在某些只能使用单个语句的地方,可以使用语句块实现多条语句的执行。 [code] 4、函数
格式:
function fname() { ..... }[/code]四、命令1、break:可以在控制条件未满足之前,跳出for、while或until循环。2、”:”命令:它是一个空命令。偶尔用于简化条件逻辑,相当于true的别名。while true ===== while :3、continue:这个命令使for、while或until循环跳到下一循环继续执行。4、”.” 命令:用于在当前shell中执行命令通常,当一个脚本执行一条外部命令或脚本程序时,会启动一个新的shell,命令将在这个新环境中执行,执行完毕之后,环境会被丢弃,留下退出码返回给父shell。 但外部source命令和点命令在执行脚本程序中列出的命令时,使用的是调用该脚本程序的同一个shell。5、echo命令:用于输出。常见的一个问题是去掉换行符解决方式有:echo -n “string to output” echo -e “string to output \c”6、eval命令:允许对参数求值。7、exit n命令:使脚本程序以退出码n结束运行。126 文件不可执行 127 命令未找到 128及以上 出现一个信号8、export命令:将作为它参数的变量导出到子shell中,并使之在子shell中有效。默认情况下,在一个shell中被创建的变量在这个shell调用的下级(子)shell中是不可用的。Export命令把自己的参数创建为一个环境变量,而这个环境变量可以被当前程序调用的其他脚本和程序看见。从更技术的角度来说,被导出的变量构成从该shell衍生的任何子进程的环境变量。9、expr == $((……)) 用于算术替换,而$( )用于命令的执行和获取输出。10、trap命令:用于指定在接收到信号后将要采取的行动。一种常见用途是在脚本程序被中断时完成清理工作。trap command signal trap "rm -f temp_file" EXIT11、find命令:用于搜索文件的命令。语法: find [path] [options] [tests] [actions]选项 含义 -depth 在查看目录本身之前先搜索目录的内容 -follow 跟随符合链接 -maxdepths N 最多搜索N层目录 -mount 不搜索其他文件系统中的目录注:通常使用圆括号来强制测试和操作符的优先级12、grep(通用正则表达式解析器 General Regular ExpresiionPraser):在文件中搜索字符串语法: grep [options] PATTERN [FILES]options: -c 输出匹配行的数目,而不是输出匹配的行 -E 启用拓展表达式 -h 取消每个输出行的普通前缀,即匹配查询模式的文件名 -i 忽略大小写 -l 只列出包含匹配行的文件名,而不是输出真正的匹配行 -v 取反操作13、正则表达式,通常配合grep使用常见的特殊字符^ 指向一行的开头 $ 指向一行的结尾 . 任意单个字符 [] 方括号内包含一个字符范围,其中任何一个字符都可以被匹配特殊匹配模式
[:alnum:] | 字符与数字字符 | [:alpha:] | 字母 |
[:ascii:] | ASCII字符 | [:blank:] | 空格或制表符 |
[:cntrl:] | ASCII控制字符 | [:digit:] | 数字 |
[:graph:] | 非控制、非空格字符 | [:lower:] | 小写字母 |
[:print:] | 可打印字符 | [:punct:] | 标点符号字符 |
[:space:] | 空白符 | [:upper:] | 大写字符 |
[:xdigit:] | 十六进制数字 |
五、Shell script编写
#!/bin/bash #This is a program about CD collection #Copyright (C) 2014 #command line description #wc命令 #wc(Word Count)命令的功能为统计指定文件中的字节数、字数、行数 #并将统计结果显示输出 #-c统计字节数。 #-l统计行数 #-m统计字符数。这个标志不能与-c 标志一起使用 #-w统计字数 #grep命令 #通用正则表达式解析器 #在文件中搜索字符串 #grep [options] PATTERN [FILES] #options #-c 输出匹配行的数目 #-E 启用拓展表达式 #-h 取消每个输出行的普通前缀 #-i 忽略大小写 #-l 只列出包含匹配行的文件名 #-v 对匹配模式进行取反操作 #cut命令 #cut是一个选取命令,就是将一段数据经过分析,取出我们想要的。一般来说,选取信息通常是针对 “行”来进行分析的,并不是整篇信息分析的。 #cut [-bn] [file] 或 cut [-c] [file] 或 cut [-df] [file] #cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。 #如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。 #主要参数 #-b:以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。 #-c:以字符为单位进行分割。 #-d:自定义分隔符,默认为制表符。 #-f :与-d一起使用,指定显示哪个区域。 #-n:取消分割多字节字符。仅和-b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的<br />范围之内,该字符将被写出;否则,该字符将被排除。 #set envrironment variable menu_choice="" current_cd="" title_file="title.cdb" tracks_file="tracks.cdb" temp_file="cdb.$$" trap 'rm -f $temp_file' EXIT get_return(){ echo -e "Press return \c" read x return 0 } get_comfire(){ echo -e "Are you sure? \c" while true do read x case "$x" in y | yes | YES | Yes ) return 0;; n | NO | No | N ) echo "Canclled!" return 1;; * ) echo "Pleasse enter yes or no!" esac done } # Menu set_menu_choice(){ clear echo "Options :-" echo echo " a) Add new CD" echo " f) Find CD" echo " c) Count the CDs andtracks in the catalog" if [ "$cdcatnum" != "" ]; then echo " l) List tracks on$cdtitle" echo " r) Remove$cdtitle" echo " u) Update trackinformation for $cdtitle" fi echo " q) Quit" echo echo -e "Please enter choice then press retrun \c" read menu_choice return } insert_title(){ #insert information to title_file echo $* >> $title_file return } insert_track(){ echo $* >> $tracks_file return } add_record_tracks(){ echo "Enter track information for this CD" echo "When no more tracks enter q" cdtrack=1 #define the title of track cdttitle="" #set $cdttitle = null while [ "$cdttitle" != q ] do #input title echo -e "Track $cdtrack, track title? \c" read tmp cdttitle=${tmp%%,*} if [ "$tmp" != "$cdttitle" ]; then echo "Sorry, no commas allowed" continue fi if [ -n "$cdttitle" ]; then if [ "$cdttitle" != "q" ]; then insert_track $cdcatnum,$cdtrack,$cdttitle fi else cdtrack=$((cdtrack-1)) fi cdtrack=$((cdtrack+1)) done } add_records(){ echo -e "Enter catalog name \c" read tmp cdcatnum=${tmp%%,*} echo -e "Enter title \c" read tmp cdtitle=${tmp%%,*} echo -e "Enter type \c" read tmp cdtrack=${tmp%%,*} echo -e "Enter artist/composer \c" read tmp cdac=${tmp%%,*} #Check that they want to enter the information echo About to add new entry echo "$cdcatnum $cdtitle $cdtype $cdac" #if comfired then append it to the tille_file if get_comfire ; then insert_title $cdcatnum,$cdtitle,$cdtype,$cdac add_record_tracks else remove_records fi return } find_cd(){ if [ "$1" = "n" ]; then asklis=n else asklist=y fi cdcatnum="" echo -e "Enter a string to search for in the CD titles \c" read searchstr if [ "$searchstr" = "" ]; then return 0 fi if [ ! -e $temp_file ]; then echo"temp_file don'texist!!!!!!!!" fi grep "$searchstr" $title_file > $temp_file set $(wc -l $temp_file) linesfound=$1 case "$linesfound" in 0 ) echo "Sorry, nothing found" get_return return 0 ;; 1 ) ;; 2 ) echo "Sorry, not unique." echo "Found the following" cat $temp_file get_return 0 ;; esac IFS="," read cdcatnum cdtitle cdtype cdac < $temp_file IFS=" " if [ -z "$cdcatnum" ]; then echo "Sorry, could not extract catalog filed from $temp_file" get_return return 0 fi echo echo Catalog number: $cdcatnum echo Title: $cdtitle echo Type: $cdtype echo Artist: $cdac echo get_return if [ "$asklist" == "y" ]; then echo -e "View tracks for this CD? \c" read x if [ "$x" == "y" ]; then echo list_tracks echo fi fi return 1 } update_cd(){ if [ -z "$cdcatnum" ]; then echo "You must select a CD" find_cd n fi if [ -n "$cdcatnum" ]; then echo "Current tracks are:-" list_tracks echo echo "this will re-enter the tracks for $cdtitle" get_comfire && { grep -v "^${cdcatnum}," $tracks_file > $temp_file mv $temp_file $tracks_file echo add_record_tracks } fi return } count_cds(){ #wc -l file : statistic thecounts set $(wc -l $title_file) num_titles=$1 set $(wc -l $tracks_file) num_tracks=$1 echo found $num_titles CDs with a total of $num_tracks tracks get_return return } remove_records(){ if [ -z "$cdcatnum" ]; then echo "You must select a CD" find_cd n fi if [ -n "$cdcatnum" ]; then echo "You are about to delete $cdtitle" get_comfire && { grep -v "^${cdcatnum}," $title_file > $temp_file mv $temp_file $title_file grep -v "^${cdcatnum}," $tracks_file > $temp_file mv $temp_file $tracks_file cdcatnum="" echo Entry removed } get_return fi return } list_tracks(){ if [ "$cdcatnum" == "" ]; then echo "No CD selected yet" return else grep -v "^${cdcatnum}," $tracks_file > $temp_file num_tracks=$(wc -l $temp_file) if [ "$num_tracks" = "0" ]; then echo no tracks found for $cdtitle else { echo echo "$cdtitle :-" echo cut -f 2- -d , $temp_file echo } | ${PAGER:-more} fi fi get_return return } #rm -f $temp_file if [ ! -f $title_file ]; then touch $title_file fi if [ ! -f $tracks_file ]; then touch $tracks_file fi if [ ! -f "$temp_file" ]; then touch $temp_file fi #Now the application proper clear echo echo echo "Mini CD manager" sleep 1 quit=n if [ -e $temp_file ]; then echo "temp_file don't exist!!!" return EXIT fi while [ "$quit" != "y"]; do set_menu_choice case "$menu_choice" in a) add_records;; r) remove_records;; f) find_cd y;; c) count_cds;; l) list_tracks;; b) echo more $title_file echo get_return;; q| Q ) quit=y;; *) echo "Sorry, choice not recoginzed";; esac done #Tidy up and leave rm -f $temp_file echo "Finished" exit 0
运行结果
显示主目录
添加CD
添加成功之后返回结果:
查找CD:
删除CD:
结束脚本:
相关文章推荐
- Linux程序设计——shell
- shell 程序设计2--- 那些年我们一起学习linux程序设计
- Linux程序设计-学习笔记-第二章shell程序设计
- shell 程序设计3--- 那些年我们一起学习linux程序设计
- linux程序设计——shell程序设计(第二章)
- linux程序设计——shell程序设计(第二章)
- Linux程序设计--shell程序设计基础(一)
- shell 程序设计1--- 那些年我们一起学习linux程序设计
- Linux shell 程序设计
- linux c/c++ 程序设计(二)shell程序编程
- Linux基础之简易Shell 程序设计
- Linux程序设计第二章 shell程序设计 笔记
- Linux程序设计之shell程序设计
- linux 程序设计笔记 第二章 shell
- Linux程序设计笔记 第2章shell程序设计
- Linux程序设计--shell程序设计基础(二)
- linux程序设计——shell程序设计(第二章)
- 5)Linux程序设计入门--信号处理
- 4)Linux程序设计入门--时间概念
- Linux 程序设计 1,2章摘要