shell 以及shell编程

shell是一种命令语言,同时又是一种程序设计语言。
shell的语言处理能力,使得用户能够方便地定义各种变量、参数,并使用各种控制语句编写复杂的命令程序完成多种工作。
本课介绍shell、shell程序设计语言、shell的运行环境及shell程序的实例。
5.1   shell概述
5.1.1 什么是shell
shell是一种命令解释程序(命令解释器),shell解释用户输入的命令行,提交系统内核处理,并将结果返回给用户。与Linux命令一样都是实用程序,但两者又有区别。一旦用户注册到系统后,shell就被系统装入内存,并一直运行到用户退出系统之止;而一般命令仅当被调用时,才由系统装入内存执行。
shell本身也是一种可编程的程序设计语言。用shell写的程序(shell脚本)相当于dos/windows下的批处理文件,它可以简单到只有一条命令,也可以复杂到包括大量循环、条件语句、数学运算、控制结构,也可以是介于两者之间的程序。
5.1.2 shell程序语言的特点
shell允许通过编程来完成复杂的功能处理,但其作为语言与高级语言相比较具有不同的特点:
(1) shell是解释性的,多数高级语言是编译性的;
(2) shell语言与高级语言处理的对象不同;
(3) shell与系统有密切的关系;
(4) shell易编写、调试、灵活性较强,但速度低;
(5) shell作为命令级语言,命令组合功能很强。
5.1.3 bash的特点
shell有两种主要语法类型: Bourne shell和C shell,彼此不兼容。Bourne shell家族:sh ksh bash psh zsh;C shell家族:csh tcsh。
其中bash和 zsh在不同程度上支持 csh 的语法。
这里,我们再着重介绍一下bash的特点:
(1) 自动补全功能
假设要输入的命令很长,或者命令后面要给的文件名很长。这个时候只要按一个Tab键,bash就会在可能的命令或文件名里面找寻匹配的命令,找到的话就会自动帮你补齐。
(2) 命令行编辑程序
bash的命令行编辑是在提示符下,可对未执行的命令字符任意地修改。
(3) 命令历史(command history)
所谓的命令历史就是把曾经输入过的命令记录起来,方便日后的查询与使用。只要按向上键就可以调出前一个命令,再按一次向上键就可以调出更前一个命令,依此类推,用向下键可以回到下个命令,所以用上、下键就可以选择以前输入过的命令。
5.1.4 Shell程序的创建与执行
• 用任一文本编辑器创建shell文件 (xxx)
(例如: gedit xxx)
• 将shell文件改为可执行文件
(例如:$chmod u+x xxx)
• 执行shell文件
(例如:$./ xxx)
5.1.5 Shell程序示例
• 以test运行“附件”中“文本编辑器”程序 gedit
• 在新建空白文档中输入如下内容:
date
pwd
cd ..
• 保存文件到   / home/test /xxx 中
• 修改文件权限,运行“系统工具”中“终端”,输入:
chmod u+x xxx <Enter>
• 输入 ./xxx <Enter>
• 5.2   shell变量
• 5.2.1 shell变量描述
• shell实际上是基于字符串的程序设计语言,但也有变量。shell变量能够而且只能存储正文字符串,即它只有一种类型的变量即串变量。但从赋值的形式上看,则可以分成四种类型的变量或变量形式。变量的名字必须以字母或下划线开头,可以包括字母、数字和下划线。
• 5.2.2 用户自定义变量
• 用户自定义变量语法格式:name=string,赋值号“=”两边不允许有空白符。
• 例:
•   nodehost=beijing.UUCP
•   path=/bin:/usr/bin:/etc/bin
•   count=10
• 允许多个赋值操作,按从右到左的顺序进行。
• 例:
•   $A=$B B=abc C=″OK″
•   $ echo $A $B $C
•   abc abc OK
• 当引用一个未设置的变量时,其隐含值为空。
• 例:
•   $ echo ″$mail is path of mailbox″
•   is path of mailbox
• 如果用双引号“”将值括起来,则括起来的字符串允许出现空格、制表符和换行符等特殊字符,而且允许有变量替换。
•   例1:$ MAIL=/var/mail/fk
•   $ var=″$MAIL is path of mailbox″
•   $ echo $var
•   /var/mail/fk is path of mailbox
• 例2:
•   $ str=″This is \n a book″
•   $ echo $str
•   This is
•   a book
• 如果用单引号‘’将值括起来,则括起来的字符串允许出现空格、制表符和换行符的特殊字符,但不允许有变量替换。
• 例3:
•   $ BOOK=″English book″
•   $ MSG=′$BOOK′
•   $ echo $MSG
•   $BOOK
• 例4:
•   $ msg=′ Today is Sunday′
•   $ echo $msg
•   Today is Sunday
• 如果用单引号‘’将值括起来,则括起来的字符串允许出现空格、制表符和换行符的特殊字符,但不允许有变量替换。
• 例3:
•   $ BOOK=″English book″
•   $ MSG=′$BOOK′
•   $ echo $MSG
•   $BOOK
• 例4:
•   $ msg=′ Today is Sunday′
•   $ echo $msg
•   Today is Sunday
• 5.2.3 位置变量
• 位置变量顾名思义是与变量所在位置有关的变量,这是一种特殊的变量。当一个shell过程被调用时,shell隐含地为它建立一系列的位置变量。这种位置变量是系统预定义好的,可以直接引用。如命令行的shell过程名本身被指定为位置变量$0,第一个命令参数为$1,……,第九个命令参数为$9。
• 例:
•   ls        /       /bin     /etc     /usr/bin     /dev
•   $0   $1    $2     $3        $4         $5
• 5.2.4 环境变量
• shell执行环境由一系列环境变量组成,这些变量是由shell维护和管理的。所有这些变量都可被用户重新设置,变量名由大写字母或数字组成。
• CDPATH    执行cd命令时使用的搜索路径;
• HOME        用户的home目录;
• PATH          寻找命令或可执行文件的搜索路径;
• PS1              主命令提示符,默认为“$”;
• PS2              从命令提示符,默认为“>”;
• TERM         使用的终端类型。
• PS1中可用信息
/$   用$作为提示符
//    显示/
/d   显示当前日期
/h   显示主机名
/s   显示shell名
/t    显示当前时间(24)
/T   显示当前时间(12)
/@   显示当前时间(AM/PM)
/u   显示用户名
/v   显示bash的版本
/W   显示当前工作目录
/w   显示当前工作路径
5.2.5 预定义的特殊变量
在shell中有一组特殊的变量,其变量名和变量值只有shell本身才可以设置。
“$#” 记录传递给shell的自变量个数。
例1:
myprog a b c                 则 $#的值为3
例2:
if test $# -lt 2
then
echo ″ two or more args required ″
exit
fi
“$?”取最近一次命令执行后的退出状态:执行成功返回码为0,执行失败返回码为1。
例:
$test -r my-file(假设my-file文件不可读)
$echo$?
1
“$$”记录当前shell的进程号。
5.3   shell中特殊字符
在shell中所使用的许多特殊符号也可为其他目的所使用,包括通配符、转义符、单引号和双引号。
1. 通配符
*       匹配任何字符串,包括空字符串;
?     匹配任何单个字符;
[.,-,!]     按照范围、列表或不匹配等形式匹配指定的字符;
\     转意符,使元字符失去其特殊的含义。
例:
[a-d,x,y]    匹配字符a、b、c、d、x、y;
z*      匹配以字符z开始的任何字符串;
x?y        匹配以x开始、以y结束、中间为任何单个字符的字符串;
[!Z] 匹配不为Z的单个字符。
通配符作为文件扩展名的使用
例:
[a-f]*    匹配字符a到字符f开头的文件名,如abc,d2,e3.c,f.dat;
*z           匹配以字符z结尾的任何字符串,如win.z,core.zz,a-c-5z;
rc?.d      匹配以rc开始、以.d结束、中间为任何单个字符的文件名,如rc0.d,rc2.d,rcS.d;
*[!o] 匹配不以o结尾的文件名。
$ back.sh
Enter your name: john
Hello john
2. 单引号 (‘’)
使用单引号消除被括在单引号中的所有特殊字符的含义,即单引号表示内容照原样不动。
例1:
$echo ′type a $* please′
type a $* please
例2: 在指定的目录中,查找名字为 *.zh 或 $.sh文件。
$cat test.sh
grep ′*.zh | $.sh′ $1
3. 双引号 (“”)
使用双引号能消除被括在双引号中的大部分特殊字符的含义,不能消除的字符有:$、 ` 、″、 \。
例1:$echo ″ Type a \$*, please ″
      Type a $*, please
例2:
vdate= ″`date` is the system maintenance time ! ″
例3: $cat share-file
      mkdir /tmp/fk
      chmod 755 /tmp/fk
      cp ″$@″ /tmp/fk
          chmod 777 /tmp/fk/*
4 反撇号(``)
当一个字符串被括在反撇号“ ` ”中时,该字符串将作为命令被shell解释执行,即用命令的执行结果替换这个字符串本身。要注意反撇号与单引号的区别。
例1:$ now=′date′
     $ echo $now
     date
     $ now=`date`
     $ echo $now
     1998年 10月 28日 星期三 17时 51分 56秒 CST
例2:$ count=10
     $ count=`expr $count+1`
     $ echo $count
     11
5. 转义符(\)
使用转义符消除单个字符的特殊含义,即将紧跟在转义符后面的单个字符按字符本身的实际含义解释。
例:转义符具有续行功能
$ cat back.sh
echo ″Enter your name: \\c″
read name
echo Hello $name
这些控制字串是:
\b    退格
\c    显示后不换行
\f     在终端上屏幕的开始处显示
\n    换行
\r    回车
\t     制表符
\v    垂直制表符
\      反斜杠
6. 管道的概念
管道:是一个命令的标准输出与另一个命令的标准输入之间的连接,不经过任何中间文件;
管道线:是由管道操作符分隔的一个命令序列,最简单的管道线是一个简单命令;
管道操作符:用符号“|”表示。
例:
w|wc -l
ps aux|grep ftp
&           表示前面的管道线在后台(异步)执行。
例1: 四个管道线构成一个命令表
ls -l /tmp /root
w|wc -l
ps
例2: 与例1等价
ls -l /tmp /root ;w|wc -l ;ps
例3:
sys-account &
7. 输入、输出重定向符
使用标准改向符进行重定向(改向)
<       输入改向
<<    追加输入改向
>      输出改向
>>    追加输出改向
使用标准文件描述字进行重定向(改向)
在Linux系统中,定义了用于输入、输出的标准文件,其文件描述字0为进程的标准输入、文件描述字1为标准输出、文件描述字2为标准错误输出。
标准错误输出的改向(>、>>)
格式为:
command 2 >file
command 2 >>file
例1: 将myfile1作为sort的输入。
sort <myfile1
例2: 将date的输出转向到myfile2文件中。
date >myfile2
例3: 将ls /|l的输出追加到myfile3文件中。
ls -l>>myfile3
例4:将错误输出改向到err-file文件。
$myprog 2>err-file
例5:将标准输出和错误输出改向out文件。
$myprog >out 2>>out
$myprog >out 2>>&1
5.4   shell的控制结构
5.4.1 条件与test命令
在程序设计语言中,作出决策的结构称为条件。在高级语言中决策的作出是依赖于基本运算的结果;在shell语言中,作出决策所依赖的条件是所执行命令的“出口状态”。
当shell命令或程序执行成功时,它返回一个“零”出口状态(即$?为零);如果执行的命令或程序出错时,则返回一个“非零”的出口状态(即$?不为零)。
除了一般命令的出口状态外,UNIX还提供了两个命令true和false的出口状态。true的出口状态为零;而false的出口状态为非零。shell将true和false命令作为恒真和恒假条件使用。
例: 判断所给出的参数是否为一个目录。
$cat check.dir
test -d $1 && echo ″ $1 is a dictory ″ && exit 0
echo ″ $1 is not a dictroy ″
exit 1
在上例中,使用了exit命令。它是一个shell的内部命令,用于终止shell程序的执行。该命令可带一个定义出口状态值的自变量。
例:
exit(0): 终止程序的执行,并返回零值;
exit(1)或exit(x): 终止程序的执行,并返回非零值;
将命令返回零出口状态称为返回“真值”;
将命令返回非零出口状态称为返回“假值”。
1. test命令
test命令是shell程序设计的条件判断中最常用的测试命令,它有两种等价的格式:
test expression或[expression](注意:[ ]中的空格)
其中expression就是要测试的条件。如果test计算expression的结果为真,则返回“零”出口状态,否则返回“非零”出口状态。test命令可用于对字符串、整数及文件进行各类测试。
2. test字符串测试表达式
例1: 两个字符串进行比较
$ user=smith
$ test ″$user″= smith
$ echo $?
0
$ test ″$user″ = tom
$ echo $?
1v例2: 带有空格的字符串比较
$ month=″January ″
$ test ″$month″ = January
$ echo $?
1
$ test $month = January
$ echo $?
0
注意: shell在处理变量时,遇到有双引号将保留其内容,而省略双引号时,将滤去空格。
例3: 带有空格的字符串比较
$ a=″testing string″
$ test ″$a″ = ″testing string″
$ echo $?
0
$ test $a = ″testing string″
test: unknown operator string
shell处理变量 $a 时,将其进行变量替换,然后将结果(testing string)传递给test,而test将string作为操作符来处理,因此出错。
例4: 带有空串(或未设置的字符串比较)
$ name=
$ test ″$name″ = smith
$ echo $?
1
$ test $name = smith
test: argument expected
shell处理变量$name时,双引号将其括起的内容作为一个“位置持有者”来保留,并把该值传递给test,保证处理的正常执行。
例5: 带有空串的字符串比较
$ blanks=″″
$ test $blanks
$ echo $?
1
$ test ″$blanks″
$ echo $?
0
shell处理变量$blanks时,将空格滤去,使其变为空串传递给test;而双引号保留 “位置持有者”的位置,其值为一个空格(空白符),传递给test。
例6: 带有算符的字符串比较
$ symvar=″=″
$ echo ″$symvar″
=
$ test -z ″$symvar″
test: argument expected
出错的原因是“=”运算符比“-z”运算符的优先级要高,因此,test 命令期望在等号之后要有一个自变量。为避免上述问题发生,可用下面命令形式替换:
$ test x″$symvar″ = x
$ echo $?
1
3. 使用test测试字符串时要注意的问题
(1) 向test 传递的各自变量之间必须有空白字符,如果“=”与任一自变量之间没有空白字符就会产生错误。
(2) 在使用变量的值替换的自变量上,用双引号括起来十分必要,以保证test在变量的值为空时也能接收到该自变量,这是一种良好的shell程序设计风格。
(3) 在test命令的测试中,空格和引号是shell程序设计中经常发生错误的焦点,要特别引起注意。
(4) test命令对它的自变量非常讲究,在比较的串中出现运算符时,要考虑到运算符优先级的问题。
4. test命令可用于整数比较
首先要搞清楚整数比较的两个概念: shell并不区分放在shell变量中的值的类型,就变量本身而言,它存放的仅仅是一组字符串,即shell只有一种类型的变量——串变量;当使用整数比较操作符时,是test命令来解释存放在变量中的整数值,而不是shell。
命令格式为,
test 整数测试表达式s
例1:
$ x1= ″ 005 ″
$ x2= ″ 10″
$ test ″ $x1 ″ = 5
$ echo $?
1
例2:
$ test ″ $x1 ″ -eq 5
$ echo $?
0
例3:
$ test ″ $x2 ″ -eq 10
$ echo $?
0
5. test用于文件的测试
test可用于文件各种特性的检查。这些文件的操作符自然是一原操作符,意味着它们要求其后跟随一个自变量。在所有的情况中,这个自变量是一个文件或目录名。常用的文件测试表达式示例如下:
例1: 检查指定的文件是否存在并且可读
test -f /usr/fk/message
例2: 检查指定的文件是否为目录
test -d /usr/src/local/sendmail
例3: 检查指定的出错文件是否为空,如不空则列出该文件的内容
test -s $errfile && {echo ″Errors found:″;\
cat $errfile}
6. 表达式的逻辑运算
在实际应用中常需要将多个表达式用逻辑运算符组合起来,构成比较复杂的条件。逻辑运算符包括:
! :     逻辑非单目运算符,可放置在任何其他test表达式之前,求得表达式运算结果的非值。
-a :   逻辑与运算符,执行两个表达式的逻辑与运算,并且仅当两者都为真时,才返回真值。
-o :   逻辑或运算符,执行两个表达式的逻辑或运算,并只要当两者之一为真时,就返回真值。
逻辑运算符优先级(由高到低) 的排列顺序如下:
( )    !    -a    -o
逻辑运算符优先级要比字符串操作符、数字比较操作符、文件操作符的优先级低。
例1: 当指定的文件不可读时为真。
test ! -r /usr/fk/message
例2: 当指定的文件均存在,且message为可读、$mailfile 指定的文件为普通文件时,返回真。
test -r /usr/fk/message -a -f ″$mailfile ″
例3: 当变量值大于等于0并且小于10时为真。
test ″$count ″ -ge 0 -a ″$count ″ -lt 10
例4: 当变量$a等于0或者$b大于5,并且$c小于等于8时为真。
test \(″$a″ -eq 0 -o ″$b″ -gt 5 \)-a ″$c″ -le 8
5.4.2 if结构
1. if的简单结构
格式为,
if command
   then
    command
    command
...
fi
2. if的完整结构
格式为,
if command
   then
    command
    command
...
   else
    command
    command
...
fi
3. if的连用结构
格式1
if command
   then
    commands
   else
    if command
    then
     commands
    else
   …
    if command
    then
     commands
    fi
   ...
   fi
fi
格式2
if command
   then
    commands
   elif command
    then
     commands
   elif
   …
   elif commands
    then
     commands
    else
     commands
fi
5.4.3 case结构
格式为,
case value in
   pattern1) command
    ...
     command;;
   pattern2) command
    ...
     command;;
    ...
   patternn) command
    ...
     command;;
   esac
5.4.4 for结构
格式为,
for variable in arg1 arg2 ... argn
do
   command
    ...
   command
   done
5.4.5 while结构
格式为,
while command
do
   command
    ...
   command
   done
5.4.6 until结构
格式为,
until command
do
   command
    ...
   command
   done
5.4.7 循环体中其他命令
1. break命令
格式为,
break或break n
break是shell的内部命令,用于在循环体中根据命令运行的返回条件,直接终止循环体内命令的执行。当执行break命令时,控制流从循环体中转移到done之后的第一条命令上。当执行break n命令时,则终止最内层的n个循环的执行。
2. continue 命令
格式为,
continue或continue n
continue是shell的内部命令,用于在循环体中根据命令运行的返回条件,直接进入下一次循环命令的执行。当执行continue命令时,控制流直接转到本循环体中第一条命令上。当执行continue n命令时,则跳过最里层的 n次循环体的执行,即开始第n个(从内向外数) 循环的下一个循环过程。
5.5 shell 程序实例-shell菜单程序
1.程序功能描述
编写一个shell程序,使用shell编写一个菜单,分别实现列出以下内容:(1)目录内容、(2)切换目录、(3)创建文件、(4)编辑文件、(5)删除文件的功能。在此例中将用到循环语句until、分支语句case、输入输出语句read和echo。
2.建立shell程序menu如下
#!/bin/sh
until
    echo "(1)List you selected directory"
    echo "(2)Change to you selected directory"
    echo "(3)Creat a new file"
    echo "(4)Edit you selected file"
    echo "(5)Remove you selected file"
    echo "(6)Exit Menu"
    read input
    test $input -eq 6
do
        case $input in
        1) ls;;
        2) echo "Enter target directory:"
           read dir
           cd $dir
           ;;
        3) echo "Enter a file name:"
           read file
           touch $file
           ;;
          4) echo "Enter a file name:"
           read file
           vi $file
           ;;
        5) echo "Enter a file name:"
           read file
           rm $file
           ;;
        *) echo "Please selected 1/2/3/4/5/6 " ;;
       esac
     done
          4) echo "Enter a file name:"
           read file
           vi $file
           ;;
        5) echo "Enter a file name:"
           read file
           rm $file
           ;;
        *) echo "Please selected 1/2/3/4/5/6 " ;;
       esac
     done

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值