shell技巧(一)

等于 :equal to
不等于:unequal to
大于 :greater
小于 :less than

1.test测试命令
test命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试,
其测试符和相应的功能分别如下:
(1)数值测试:
-eq:等于则为真
-ne:不等于则为真
-gt:大于则为真
-ge:大于等于则为真
-lt:小于则为真
-le:小于等于则为真
(2)字符串测试:
=:等于则为真
!=:不相等则为真
-z字符串:字符串长度伪则为真
-n字符串:字符串长度不伪则为真
(3)文件测试:
-e文件名:如果文件存在则为真
-r文件名:如果文件存在且可读则为真
-w文件名:如果文件存在且可写则为真
-x文件名:如果文件存在且可执行则为真
-s文件名:如果文件存在且至少有一个字符则为真
-d文件名:如果文件存在且为目录则为真
-f文件名:如果文件存在且为普通文件则为真
-c文件名:如果文件存在且为字符型特殊文件则为真
-b文件名:如果文件存在且为块特殊文件则为真
另外,Linux还提供了与(“!”)、或(“-o)、非(“-a”)三个逻辑操作符用于将测试条件连接起来,
其优先级为:“!”最高,“-a”次之,“-o”最低。
同时,bash也能完成简单的算术运算,格式如下:
$[expression]
例如:var1=2
var2=$[var1*10 1]
则:var2的值为21。

2.if条件语句
if[-x/sbin/quotaon];then
echo"TurningonQuotaforrootfilesystem"
/sbin/quotaon/
elif[-x/sbin/quotaon];then
/usr/bin/bash
else
echo"ok"
fi

3.for循环
#!/bin/sh
WORD="abcdefghijlmnopqrstuvwxyz"
foriin$WORD;do
echo$i
done

#!/bin/sh
FILES=`ls/txt/*.txt`
fortxtin$FILES;do
doc=`echo$txt|sed"s/.txt/.doc/"`
mv$txt$doc
done

4.while和until循环
#!/bin/sh
while[-f/var/run/ppp0.pid];do
killallpppd
done

#!/bin/sh
until[-f/var/run/ppp0.pid];do
sleep1
done

Shell还提供了true和false两条命令用于建立无限循环结构的需要,
它们的返回状态分别是总为0或总为非0

5.case条件选择
#!/bin/sh
case$1in
start|begin)
echo"startsomething"
;;
stop|end)
echo"stopsomething"
;;
*)
echo"Ignorant"
;;
esac
case表达式中也可以使用shell的通配符(“*”、“?”、“[]”)。

6.无条件控制语句break和continue
break用于立即终止当前循环的执行,而contiune用于不执行循环中后面的语句
而立即开始下一个循环的执行。这两个语句只有放在do和done之间才有效。

7.函数定义
在shell中还可以定义函数。函数实际上也是由若干条shell命令组成的,
因此它与shell程序形式上是相似的,不同的是它不是一个单独的进程,
而是shell程序的一部分。函数定义的基本格式为:
functionname
{
若干命令行
}
调用函数的格式为:
functionnameparam1param2……
shell函数可以完成某些例行的工作,而且还可以有自己的退出状态,
因此函数也可以作为if、while等控制结构的条件。
在函数定义时不用带参数说明,但在调用函数时可以带有参数,此时
shell将把这些参数分别赋予相应的位置参数$1、$2、...及$*。

8.命令分组
在shell中有两种命令分组的方法:“()”和“{}”,前者当shell执行()
中的命令时将再创建一个新的子进程,然后这个子进程去执行圆括弧中的命令。
当用户在执行某个命令时不想让命令运行时对状态集合(如位置参数、环境变量、
当前工作目录等)的改变影响到下面语句的执行时,就应该把这些命令放在圆括
弧中,这样就能保证所有的改变只对子进程产生影响,而父进程不受任何干扰;
{}用于将顺序执行的命令的输出结果用于另一个命令的输入(管道方式)。当我们
要真正使用圆括弧和花括弧时(如计算表达式的优先级),则需要在其前面加上转
义符(\)以便让shell知道它们不是用于命令执行的控制所用。

9.信号
trap命令用于在shell程序中捕捉到信号,之后可以有三种反应方式:
(1)执行一段程序来处理这一信号
(2)接受信号的默认操作
(3)忽视这一信号
trap对上面三种方式提供了三种基本形式:
第一种形式的trap命令在shell接收到signallist清单中数值相同的信号时,
将执行双引号中的命令串。
trap'commands'signal-list
trap"commands"signal-list
为了恢复信号的默认操作,使用第二种形式的trap命令:
trapsignal-list
第三种形式的trap命令允许忽视信号:
trap""signal-list
注意:
(1)对信号11(段违例)不能捕捉,因为shell本身需要捕捉该信号去进行内存的转储。
(2)在trap中可以定义对信号0的处理(实际上没有这个信号),shell程序在其终止
(如执行exit语句)时发出该信号。
(3)在捕捉到signal-list中指定的信号并执行完相应的命令之后,如果这些命令没有将
shell程序终止的话,shell程序将继续执行收到信号时所执行的命令后面的命令,这样
将很容易导致shell程序无法终止。
另外,在trap语句中,单引号和双引号是不同的,当shell程序第一次碰到trap语句时,
将把commands中的命令扫描一遍。此时若commands是用单引号括起来的话,那么shell
不会对commands中的变量和命令进行替换,否则commands中的变量和命令将用当时具体
的值来替换。

10.运行shell程序的方法
执行shell程序的方法有三种:
(1)shshell程序文件名
格式为:
bashshell程序文件名
这实际上是调用一个新的bash命令解释程序,而把shell程序文件名作为参数传递给它。
新启动的shell将去读指定的文件,执行文件中列出的命令,当所有的命令都执行完结束。
该方法的优点是可以利用shell调试功能。
(2)sh<shell程序文件名
格式为:
bash<shell程序文件名
这种方式就是利用输入重定向,使shell命令解释程序的输入取自指定的程序文件。
(3)用chmod命令使shell程序成为可执行的

11.bash程序的调试
bash-选择项shell程序文件名
几个常用的选择项是:
-e:如果一个命令失败就立即退出
-n:读入命令但是不执行它们
-u:置换时把未设置的变量看作出错
-v:当读入shell输入行时把它们显示出来
-x:执行命令时把命令和它们的参数显示出来
上面的所有选项也可以在shell程序内部用“set-选择项”的形式引用,而“set 选择项”则
将禁止该选择项起作用。如果只想对程序的某一部分使用某些选择项时,则可以将该部分用
上面两个语句包围起来。
1.未置变量退出和立即退出
未置变量退出特性允许用户对所有变量进行检查,如果引用了一个未赋值的变量就终止shell
程序的执行。shell通常允许未置变量的使用,在这种情况下,变量的值为空。如果设置了未
置变量退出选择项,则一旦使用了未置变量就显示错误信息,并终止程序的运行。未置变量退
出选择项为“-u”。
当shell运行时,若遇到不存在或不可执行的命令、重定向失败或命令非正常结束等情况时,如
果未经重新定向,该出错信息会打印在终端屏幕上,而shell程序仍将继续执行。要想在错误发
生时迫使shell程序立即结束,可以使用“-e”选项将shell程序的执行立即终止。
2.shell程序的跟踪
调试shell程序的主要方法是利用shell命令解释程序的“-v”或“-x”选项来跟踪程序的执行。“-v”
选择项使shell在执行程序的过程中,把它读入的每一个命令行都显示出来,而“-x”选择项使shell
在执行程序的过程中把它执行的每一个命令在行首用一个“ ”加上命令名显示出来。并把每一个变量
和该变量所取的值也显示出来,因此,它们的主要区别在于:在执行命令行之前无“-v”则打印出命
令行的原始内容,而有“-v”则打印出经过替换后的命令行的内容。
除了使用shell的“-v”和“-x”选择项以外,还可以在shell程序内部采取一些辅助调试的措施。
例如,可以在shell程序的一些关键地方使用echo命令把必要的信息显示出来,它的作用相当于C语
言中的printf语句,这样就可以知道程序运行到什么地方及程序目前的状态。

12.bash的内部命令
bash命令解释程序包含了一些内部命令。内部命令在目录列表时是看不见的,它们由shell本身提供。
常用的内部命令有:echo、eval、exec、export、readonly、read、shift、wait和点(.)。
下面简单介绍其命令格式和功能。
1.echo
命令格式:echoarg
功能:在屏幕上打印出由arg指定的字符串。
2.eval
命令格式:evalargs
功能:当shell程序执行到eval语句时,shell读入参数args,并将它们组合成一个新的命令,然后
执行。
3.exec
命令格式:exec命令命令参数
功能:当shell执行到exec语句时,不会去创建新的子进程,而是转去执行指定的命令,
当指定的命令执行完时,该进程,也就是最初的shell就终止了,所以shell程序中exec
后面的语句将不再被执行。
4.export
命令格式:export变量名或:export变量名=变量值
功能:shell可以用export把它的变量向下带入子shell从而让子进程继承父进程中的环境变量。
但子shell不能用export把它的变量向上带入父shell。
注意:不带任何变量名的export语句将显示出当前所有的export变量。
5.readonly
命令格式:readonly变量名
功能:将一个用户定义的shell变量标识为不可变的。不带任何参数的readonly命令将显示出
所有只读的shell变量。
6.read
命令格式:
read变量名表
功能:从标准输入设备读入一行,分解成若干字,赋值给shell程序内部定义的变量。
7.shift语句
功能:shift语句按如下方式重新命名所有的位置参数变量:$2成为$1,$3成为$2……在程序中
每使用一次shift语句,都使所有的位置参数依次向左移动一个位置,并使位置参数“$#”减一,
直到减到0。
8.wait
功能:是shell等待在后台启动的所有子进程结束。Wait的返回值总是真。
9.exit
功能:退出shell程序。在exit之后可有选择地指定一个数字作为返回状态。
10.“.”(点)
命令格式:.Shell程序文件名
功能:使shell读入指定的shell程序文件并依次执行文件中的所有语句。

13.特殊参数:
1.$*:代表所有参数,其间隔为IFS内定参数的第一个字元
2.$@:与*星号类同。不同之处在於不参照IFS
3.$#:代表参数数量
4.$?:执行上一个指令的返回值
5.$-:最近执行的foregroundpipeline的选项参数
6.$$:本身的ProcessID
7.$!:执行上一个背景指令的PID
8.$_:显示出最後一个执行的命令


巩固(二)


测试的标志 代表意义 
1. 关于某个档名的『类型』侦测(存在与否),如 test -e filename 
-e 该『档名』是否存在?(常用) 
-f 该『档名』是否为档案(file)?(常用) 
-d 该『文件名』是否为目录(directory)?(常用) 
-b 该『档名』是否为一个 block device 装置? 
-c 该『档名』是否为一个 character device 装置? 
-S 该『档名』是否为一个 Socket 档案? 
-p 该『档名』是否为一个 FIFO (pipe) 档案? 
-L 该『档名』是否为一个连结档? 
2. 关于档案的权限侦测,如 test -r filename 
-r 侦测该档名是否具有『可读』的属性? 
-w 侦测该档名是否具有『可写』的属性? 
-x 侦测该档名是否具有『可执行』的属性? 
-u 侦测该文件名是否具有『SUID』的属性? 
-g 侦测该文件名是否具有『SGID』的属性? 
-k 侦测该文件名是否具有『Sticky bit』的属性? 
-s 侦测该档名是否为『非空白档案』? 
3. 两个档案之间的比较,如: test file1 -nt file2 
-nt (newer than)判断 file1 是否比 file2 新 
-ot (older than)判断 file1 是否比 file2 旧 
-ef 判断 file2 与 file2 是否为同一档案,可用在判断 hard link 的判定上。 主要意义在判定,两个档案是否均指向同一个 inode 哩! 
4. 关于两个整数之间的判定,例如 test n1 -eq n2 
-eq 两数值相等 (equal) 
-ne 两数值不等 (not equal) 
-gt n1 大于 n2 (greater than) 
-lt n1 小于 n2 (less than) 
-ge n1 大于等于 n2 (greater than or equal) 
-le n1 小于等于 n2 (less than or equal) 
5. 判定字符串的数据 
test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true 
test -n string 判定字符串是否非为 0 ?若 string 为空字符串,则为 false。 
注: -n 亦可省略 
test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true 
test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false 
6. 多重条件判定,例如: test -r filename -a -x filename 
-a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。 
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。 
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true 
=================================基础知识==============================

表示方法 描述     
$n $1 表示第一个参数,$2 表示第二个参数 ...     
$# 命令行参数的个数     
$0 当前程序的名称     
$? 前一个命令或函数的返回码     
$* 以"参数1 参数2 ... " 形式保存所有参数     
$@ 以"参数1" "参数2" ... 形式保存所有参数     
$$ 本程序的(进程ID号)PID     
$! 上一个命令的PID 
shell 环境变量是所有shell 程序都会接受的参数。shell程序运行时,都会接收一组变量,这组变量就是环境变量。常用的环境变量: 

名称 描述     
PATH 命令搜索路径,以冒号为分隔符.注意与DOS下不同的是, 当前目录不在系统路径里     
HOME 用户home目录的路径名,是cd命令的默认参数     
COLUMNS 定义了命令编辑模式下可使用命令行的长度     
EDITOR 默认的行编辑器     
VISUAL 默认的可视编辑器     
FCEDIT 命令fc使用的编辑器     
HISTFILE 命令历史文件     
HISTSIZE 命令历史文件中最多可包含的命令条数     
HISTFILESIZE 命令历史文件中包含的最大行数     
IFS 定义SHELL使用的分隔符     
LOGNAME 用户登录名     
MAIL 指向一个需要SHELL监视其修改时间的文件.当该文件修改后, SHELL将发消息You hava mail给用户     
MAILCHECK SHELL检查MAIL文件的周期,单位是秒     
MAILPATH 功能与MAIL类似.但可以用一组文件,以冒号分隔,每个文件后可跟一个问号和一条发向用户的消息     
SHELL SHELL的路径名     
TERM 终端类型     
TMOUT SHELL自动退出的时间,单位为秒,若设为0则禁止SHELL自动退出     
PROMPT_COMMAND 指定在主命令提示符前应执行的命令     
PS1 主命令提示符     
PS2 二级命令提示符,命令执行过程中要求输入数据时用     
PS3 select的命令提示符     
PS4 调试命令提示符     
MANPATH 寻找手册页的路径,以冒号分隔     
LD_LIBRARY_PATH 寻找库的路径,以冒号分隔



◎参数
    1. -A NUM,--after-context=NUM 
               除了列出符合行之外,并且列出后NUM行。
             
         ex:   $ grep -A 1 panda file 
               (从file中搜寻有panda样式的行,并显示该行的后1行)
                                 
    2. -a或--text 
               grep原本是搜寻文字文件,若拿二进制的档案作为搜寻的目标,
               则会显示如下的讯息: Binary file 二进制文件名 matches 然后结束。
                  
               若加上-a参数则可将二进制档案视为文本文件搜寻,
               相当于--binary-files=text这个参数。
            
         ex:   (从二进制档案mv中去搜寻panda样式)
               (错误!!!)
               $ grep panda mv 
               Binary file mv matches 
               (这表示此档案有match之处,详见--binary-files=TYPE )
               $
               (正确!!!)
               $ grep -a panda mv 
       
    3. -B NUM,--before-context=NUM
               与 -A NUM 相对,但这此参数是显示除符合行之外
               并显示在它之前的NUM行。        
             
         ex:   (从file中搜寻有panda样式的行,并显示该行的前1行)
               $ grep -B 1 panda file

    4. -C [NUM], -NUM, --context[=NUM] 
               列出符合行之外并列出上下各NUM行,默认值是2。
             
         ex:   (列出file中除包含panda样式的行外并列出其上下2行)
               (若要改变默认值,直接改变NUM即可)
               $ grep -C[NUM] panda file 
             
    5. -b, --byte-offset
               列出样式之前的内文总共有多少byte ..
              
          ex: $ grep -b panda file 
       显示结果类似于:
         0:panda
        66:pandahuang
       123:panda03
           
    6. --binary-files=TYPE
               此参数TYPE预设为binary(二进制),若以普通方式搜寻,只有2种结果:
                 1.若有符合的地方:显示Binary file 二进制文件名 matches
                 2.若没有符合的地方:什么都没有显示。
                   
               若TYPE为without-match,遇到此参数,
               grep会认为此二进制档案没有包含任何搜寻样式,与-I 参数相同。
                   
               若TPYE为text, grep会将此二进制文件视为text档案,与-a 参数相同。
        
     Warning: --binary-files=text 若输出为终端机,可能会产生一些不必要的输出。
              
    7. -c, --count
       不显示符合样式行,只显示符合的总行数。
       若再加上-v,--invert-match,参数显示不符合的总行数。

    8. -d ACTION, --directories=ACTION
               若输入的档案是一个资料夹,使用ACTION去处理这个资料夹。
       预设ACTION是read(读取),也就是说此资料夹会被视为一般的档案;
       若ACTION是skip(略过),资料夹会被grep略过:
       若ACTION是recurse(递归),grep会去读取资料夹下所有的档案,
       此相当于-r 参数。

    9. -E, --extended-regexp
       采用规则表示式去解释样式。
      
   10. -e PATTERN, --regexp=PATTERN
       把样式做为一个partern,通常用在避免partern用-开始。

   11. -f FILE, --file=FILE
       事先将要搜寻的样式写入到一个档案,一行一个样式。
       然后采用档案搜寻。
       空的档案表示没有要搜寻的样式,因此也就不会有任何符合。
       
   ex: (newfile为搜寻样式文件)
       $grep -f newfile file   

   12. -G, --basic-regexp
       将样式视为基本的规则表示式解释。(此为预设)

   13. -H, --with-filename
       在每个符合样式行前加上符合的文件名称,若有路径会显示路径。
       
   ex: (在file与testfile中搜寻panda样式)   
       $grep -H panda file ./testfile
                file:panda
                ./testfile:panda
                $
     
   14. -h, --no-filename 
               与-H参数相类似,但在输出时不显示路径。

   15. --help 
               产生简短的help讯息。

   16. -I
               grep会强制认为此二进制档案没有包含任何搜寻样式,
               与--binary-files=without-match参数相同。
                   
           ex: $ grep -I panda mv

   17. -i, --ignore-case      
               忽略大小写,包含要搜寻的样式及被搜寻的档案。
               
           ex: $ grep -i panda mv
                
   18. -L, --files-without-match 
               不显示平常一般的输出结果,反而显示出没有符合的文件名称。

   19. -l, --files-with-matches               
               不显示平常一般的输出结果,只显示符合的文件名称。

   20. --mmap               
               如果可能,使用mmap系统呼叫去读取输入,而不是预设的read系统呼叫。 
               在某些状况,--mmap 能产生较好的效能。 然而,--mmap 
               如果运作中档案缩短,或I/O 错误发生时,
               可能造成未定义的行为(包含core dump),。
               
   21. -n, --line-number
               在显示行前,标上行号。
               
            ex: $ grep -n panda file 
                显示结果相似于下:
                行号:符合行的内容

   22. -q, --quiet, --silent 
               不显示任何的一般输出。请参阅-s或--no-messages

   23. -r, --recursive
       递归地,读取每个资料夹下的所有档案,此相当于 -d recsuse 参数。

   24. -s, --no-messages
       不显示关于不存在或无法读取的错误讯息。
     
小注: 不像GNU grep,传统的grep不符合POSIX.2协议,
       因为缺乏-q参数,且他的-s 参数表现像GNU grep的 -q 参数。
       Shell Script倾向将传统的grep移植,避开-q及-s参数,
       且将输出限制到/dev/null。
    
POSIX: 定义UNIX及UNIX-like系统需要提供的功能。             
    
   25. -V, --version 
显示出grep的版本号到标准错误。
当您在回报有关grep的bugs时,grep版本号是必须要包含在内的。

   26. -v, --invert-match
显示除搜寻样式行之外的全部。
                   
   27. -w, --word-regexp
          将搜寻样式视为一个字去搜寻,完全符合该"字"的行才会被列出。

   28. -x, --line-regexp
将搜寻样式视为一行去搜寻,完全符合该"行"的行才会被列出。


2010-02-09