您的位置:首页 > 运维架构 > Shell

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"   EXIT

    11、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:

 

结束脚本:

 

             


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: