1: Linux shell脚本全面学习
2: [日期:2007-06-04] 来源:Linux公社 作者:Linux
3:
4: 1. Linux 脚本编写基础
5:
6: 1.1 语法基本介绍
7:
8: 1.1.1 开头
9:
10: 程序必须以下面的行开始(必须方在文件的第一行):
11:
12: #!/bin/sh
13:
14: 符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。
15:
16: 当编辑好脚本时,如果要执行该脚本,还必须使其可执行。
17:
18: 要使脚本可执行:
19:
20: 编译 chmod +x filename 这样才能用./filename 来运行
21:
22: 1.1.2 注释
23:
24: 在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。
25:
26: 如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用
27:
28: 及工作原理。
29:
30: 1.1.3 变量
31:
32: 在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量
33:
34: 进行声明。要赋值给一个变量,您可以这样写:
35:
36: #!/bin/sh
37:
38: #对变量赋值:
39:
40: a="hello world"
41:
42: # 现在打印变量a的内容:
43:
44: echo "A is:"
45:
46: echo $a
47:
48: 有时候变量名很容易与其他文字混淆,比如:
49:
50: num=2
51:
52: echo "this is the $numnd"
53:
54: 这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,
55:
56: 但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量:
57:
58: num=2
59:
60: echo "this is the ${num}nd"
61:
62: 这将打印: this is the 2nd
63:
64: 1.1.4 环境变量
65:
66: 由export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录
67:
68: 脚本中使用环境变量。
69:
70: 1.1.5 Shell命令和流程控制
71:
72: 在shell脚本中可以使用三类命令:
73:
74: 1)Unix 命令:
75:
76: 虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来
77:
78: 进行文件和文字操作的。
79:
80: 常用命令语法及功能
81:
82: echo "some text": 将文字内容打印在屏幕上
83:
84: ls: 文件列表
85:
86: wc –l filewc -w filewc -c file: 计算文件行数计算文件中的单词数计算文件中的字符数
87:
88: cp sourcefile destfile: 文件拷贝
89:
90: mv oldname newname : 重命名文件或移动文件
91:
92: rm file: 删除文件
93:
94: grep 'pattern' file: 在文件内搜索字符串比如:grep 'searchstring' file.txt
95:
96: cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出
97:
98: 每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,
99:
100: 这是两个完全不同的命令
101:
102: cat file.txt: 输出文件内容到标准输出设备(屏幕)上
103:
104: file somefile: 得到文件类型
105:
106: read var: 提示用户输入,并将输入赋值给变量
107:
108: sort file.txt: 对file.txt文件中的行进行排序
109:
110: uniq: 删除文本文件中出现的行列比如: sort file.txt | uniq
111:
112: expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3
113:
114: find: 搜索文件比如:根据文件名搜索find . -name filename -print
115:
116: tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile
117:
118: basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回 tux
119:
120: dirname file: 返回文件所在路径比如:dirname /bin/tux将返回 /bin
121:
122: head file: 打印文本文件开头几行
123:
124: tail file : 打印文本文件末尾几行
125:
126: sed: Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将
127:
128: 结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。
129:
130: 不要和shell中的通配符相混淆。比如:将linuxfocus 替换为
131:
132: LinuxFocus :cat text.file | sed 's/linuxfocus/LinuxFocus/' > newtext.file
133:
134: awk: awk 用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。
135:
136: cat file.txt | awk -F, '{print $1 "," $3 }'这里我们使用,作为字段分割符,同时打印
137:
138: 第一个和第三个字段。如果该文件内容如下: Adam Bor, 34, IndiaKerry Miller, 22, USA
139:
140: 命令输出结果为:Adam Bor, IndiaKerry Miller, USA
141:
142: 念: 管道, 重定向和 backtick
143:
144: 这些不是系统命令,但是他们真的很重要。
145:
146: 管道 (|) 将一个命令的输出作为另外一个命令的输入。
147:
148: grep "hello" file.txt | wc -l
149:
150: 在file.txt中搜索包含有”hello”的行并计算其行数。
151:
152: 在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令。
153:
154: 重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。
155:
156: > 写入文件并覆盖旧文件
157:
158: >> 加到文件的尾部,保留旧文件内容。
159:
160: 反短斜线
161:
162: 使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。
163:
164: 命令:
165:
166: find . -mtime -1 -type f -print
167:
168: 用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您
169:
170: 想将所有查找到的文件打一个包,则可以使用以下脚本:
171:
172: #!/bin/sh
173:
174: # The ticks are backticks (`) not normal quotes ('):
175:
176: tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`
177:
178: 3) 流程控制
179:
180: 1.if
181:
182: "if" 表达式 如果条件为真则执行then后面的部分:
183:
184: if ....; then
185:
186: ....
187:
188: elif ....; then
189:
190: ....
191:
192: else
193:
194: ....
195:
196: fi
197:
198: 大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件
199:
200: 是否存在及是否可读等等…
201:
202: 通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确保方括号的空格。
203:
204: [ -f "somefile" ] :判断是否是一个文件
205:
206: [ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
207:
208: [ -n "$var" ] :判断$var变量是否有值
209:
210: [ "$a" = "$b" ] :判断$a和$b是否相等
211:
212: 执行man test可以查看所有测试表达式可以比较和判断的类型。
213:
214: 直接执行以下脚本:
215:
216: #!/bin/sh
217:
218: if [ "$SHELL" = "/bin/bash" ]; then
219:
220: echo "your login shell is the bash (bourne again shell)"
221:
222: else
223:
224: echo "your login shell is not bash but $SHELL"
225:
226: fi
227:
228: 变量$SHELL包含了登录shell的名称,我们和/bin/bash进行了比较。
229:
230: 快捷操作符
231:
232: 熟悉C语言的朋友可能会很喜欢下面的表达式:
233:
234: [ -f "/etc/shadow" ] && echo "This computer uses shadow passwors"
235:
236: 这里 && 就是一个快捷操作符,如果左边的表达式为真则执行右边的语句。
237:
238: 您也可以认为是逻辑运算中的与操作。上例中表示如果/etc/shadow文件存在
239:
240: 则打印” This computer uses shadow passwors”。同样或操作(||)在shell编程中也是
241:
242: 可用的。这里有个例子:
243:
244: #!/bin/sh
245:
246: mailfolder=/var/spool/mail/james
247:
248: [ -r "$mailfolder" ]' '{ echo "Can not read $mailfolder" ; exit 1; }
249:
250: echo "$mailfolder has mail from:"
251:
252: grep "^From " $mailfolder
253:
254: 该脚本首先判断mailfolder是否可读。如果可读则打印该文件中的"From" 一行。如果不可读
255:
256: 则或操作生效,打印错误信息后脚本退出。这里有个问题,那就是我们必须有两个命令:
257:
258: -打印错误信息
259:
260: -退出程序
261:
262: 我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用。一般函数将在下文提及。
263:
264: 不用与和或操作符,我们也可以用if表达式作任何事情,但是使用与或操作符会更便利很多。
265:
266: 2.case
267:
268: case :表达式可以用来匹配一个给定的字符串,而不是数字。
269:
270: case ... in
271:
272: ...) do something here ;;
273:
274: esac
275:
276: 让我们看一个例子。 file命令可以辨别出一个给定文件的文件类型,比如:
277:
278: file lf.gz
279:
280: 这将返回:
281:
282: lf.gz: gzip compressed data, deflated, original filename,
283:
284: last modified: Mon Aug 27 23:09:18 2001, os: Unix
285:
286: 我们利用这一点写了一个叫做smartzip的脚本,该脚本可以自动解压bzip2, gzip 和zip 类型的压缩文件:
287:
288: #!/bin/sh
289:
290: ftype=`file "$1"`
291:
292: case "$ftype" in
293:
294: "$1: Zip archive"*)
295:
296: unzip "$1" ;;
297:
298: "$1: gzip compressed"*)
299:
300: gunzip "$1" ;;
301:
302: "$1: bzip2 compressed"*)
303:
304: bunzip2 "$1" ;;
305:
306: *) echo "File $1 can not be uncompressed with smartzip";;
307:
308: esac
309:
310: 您可能注意到我们在这里使用了一个特殊的变量$1。该变量包含了传递给该程序的第一个参数值。
311:
312: 也就是说,当我们运行:
313:
314: smartzip articles.zip
315:
316: $1 就是字符串 articles.zip
317:
318: . selsect
319:
320: select 表达式是一种bash的扩展应用,尤其擅长于交互式使用。用户可以从一组不同的值中进行选择。
321:
322: select var in ... ; do
323:
324: break
325:
326: done
327:
328: .... now $var can be used ....
329:
330: 下面是一个例子:
331:
332: #!/bin/sh
333:
334: echo "What is your favourite OS?"
335:
336: select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
337:
338: break
339:
340: done
341:
342: echo "You have selected $var"
343:
344: 下面是该脚本运行的结果:
345:
346: What is your favourite OS?
347:
348: 1) Linux
349:
350: 2) Gnu Hurd
351:
352: 3) Free BSD
353:
354: 4) Other
355:
356: #? 1
357:
358: You have selected Linux
359:
360: 4.loop
361:
362: loop表达式:
363:
364: while ...; do
365:
366: ....
367:
368: done
369:
370: while-loop 将运行直到表达式测试为真。will run while the expression that we test for is true.
371:
372: 关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。
373:
374: for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:
375:
376: for var in ....; do
377:
378: ....
379:
380: done
381:
382: 在下面的例子中,将分别打印ABC到屏幕上:
383:
384: #!/bin/sh
385:
386: for var in A B C ; do
387:
388: echo "var is $var"
389:
390: done
391:
392: 下面是一个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:
393:
394: #!/bin/sh
395:
396: # list a content summary of a number of RPM packages
397:
398: # USAGE: showrpm rpmfile1 rpmfile2 ...
399:
400: # EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm
401:
402: for rpmpackage in $*; do
403:
404: if [ -r "$rpmpackage" ];then
405:
406: echo "=============== $rpmpackage =============="
407:
408: rpm -qi -p $rpmpackage
409:
410: else
411:
412: echo "ERROR: cannot read file $rpmpackage"
413:
414: fi
415:
416: done
417:
418: 这里出现了第二个特殊的变量$*,该变量包含了所有输入的命令行参数值。
419:
420: 如果您运行showrpm openssh.rpm w3m.rpm webgrep.rpm
421:
422: 此时 $* 包含了 3 个字符串,即openssh.rpm, w3m.rpm and webgrep.rpm.
423:
424: 5. 引号
425:
426: 在向程序传递任何参数之前,程序会扩展通配符和变量。这里所谓扩展的意思是程序会把通配符
427:
428: (比如*)替换成合适的文件名,它变量替换成变量值。为了防 止程序作这种替换,您可以使用
429:
430: 引号:让我们来看一个例子,假设在当前目录下有一些文件,两个jpg文件, mail.jpg 和tux.jpg。
431:
432: 1.2 编译SHELL脚本
433:
434: #ch#!/bin/sh mod +x filename
435:
436: cho *.jpg ∪缓螅梢酝ü淙耄?./filename 来执行您的脚本。
437:
438: 这将打印出"mail.jpg tux.jpg"的结果。
439:
440: 引号 (单引号和双引号) 将防止这种通配符扩展:
441:
442: #!/bin/sh
443:
444: echo "*.jpg"
445:
446: echo '*.jpg'
447:
448: 这将打印"*.jpg" 两次。
449:
450: 单引号更严格一些。它可以防止任何变量扩展。双引号可以防止通配符扩展但允许变量扩展。
451:
452: #!/bin/sh
453:
454: echo $SHELL
455:
456: echo "$SHELL"
457:
458: echo '$SHELL'
459:
460: 运行结果为:
461:
462: /bin/bash
463:
464: /bin/bash
465:
466: $SHELL
467:
468: 最后,还有一种防止这种扩展的方法,那就是使用转义字符——反斜杆:
469:
470: echo *.jpg
471:
472: echo $SHELL
473:
474: 这将输出:
475:
476: *.jpg
477:
478: $SHELL
479:
480: 6. Here documents
481:
482: 当要将几行文字传递给一个命令时,here documents(译者注:目前还没有见到过对该词适合的翻译)
483:
484: 一种不错的方法。对每个脚本写一段帮助性的文字是很有用的,此时如果我们四有那个 here documents
485:
486: 就不必用echo函数一行行输出。 一个 "Here document" 以 shift by 2
487:
488: --) shift;break;; # end of options
489:
490: -*) echo "error: no such option $1. -h for help";exit 1;;
491:
492: *) break;;
493:
494: esac
495:
496: done
497:
498: echo "opt_f is $opt_f"
499:
500: echo "opt_l is $opt_l"
501:
502: echo "first arg is $1"
503:
504: echo "2nd arg is $2"
505:
506: 您可以这样运行该脚本:
507:
508: cmdparser -l hello -f -- -somefile1 somefile2
509:
510: 返回的结果是:
511:
512: opt_f is 1
513:
514: opt_l is hello
515:
516: first arg is -somefile1
517:
518: 2nd arg is somefile2
519:
520: 这个脚本是如何工作的呢?脚本首先在所有输入命令行参数中进行循环,将输入参数
521:
522: 与case表达式进行比较,如果匹配则设置一个变量并且移除该参数。根据unix系统的惯例,
523:
524: 首先输入的应该是包含减号的参数.
525:
526: 第2部分 实例
527:
528: 现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构,是一个非常不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy命令:
529:
530: cp framework.sh myscript
531:
532: 然后再插入自己的函数。
533:
534: 让我们再看两个例子:
535:
536: 二进制到十进制的转换
537:
538: 脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr命令进行数学运算的例子:
539:
540: #!/bin/sh
541:
542: # vim: set sw=4 ts=4 et:
543:
544: help()
545:
546: {
547:
548: cat <
549:
550: b2h -- convert binary to decimal
551:
552: USAGE: b2h [-h] binarynum
553:
554: OPTIONS: -h help text
555:
556: EXAMPLE: b2h 111010
557:
558: will return 58
559:
560: HELP
561:
562: exit 0
563:
564: }
565:
566: error()
567:
568: {
569:
570: # print an error and exit
571:
572: echo "$1"
573:
574: exit 1
575:
576: }
577:
578: lastchar()
579:
580: {
581:
582: # return the last character of a string in $rval
583:
584: if [ -z "$1" ]; then
585:
586: # empty string
587:
588: rval=""
589:
590: return
591:
592: fi
593:
594: # wc puts some space behind the output this is why we need sed:
595:
596: numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `
597:
598: # now cut out the last char
599:
600: rval=`echo -n "$1" | cut -b $numofchar`
601:
602: }
603:
604: chop()
605:
606: {
607:
608: # remove the last character in string and return it in $rval
609:
610: if [ -z "$1" ]; then
611:
612: # empty string
613:
614: rval=""
615:
616: return
617:
618: fi
619:
620: # wc puts some space behind the output this is why we need sed:
621:
622: numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `
623:
624: if [ "$numofchar" = "1" ]; then
625:
626: # only one char in string
627:
628: rval=""
629:
630: return
631:
632: fi
633:
634: numofcharminus1=`expr $numofchar "-" 1`
635:
636: # now cut all but the last char:
637:
638: rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`
639:
640: }
641:
642: while [ -n "$1" ]; do
643:
644: case $1 in
645:
646: -h) help;shift 1;; # function help is called
647:
648: --) shift;break;; # end of options
649:
650: -*) error "error: no such option $1. -h for help";;
651:
652: *) break;;
653:
654: esac
655:
656: done
657:
658: # The main program
659:
660: sum=0
661:
662: weight=1
663:
664: # one arg must be given:
665:
666: [ -z "$1" ] && help
667:
668: binnum="$1"
669:
670: binnumorig="$1"
671:
672: while [ -n "$binnum" ]; do
673:
674: lastchar "$binnum"
675:
676: if [ "$rval" = "1" ]; then
677:
678: sum=`expr "$weight" "+" "$sum"`
679:
680: fi
681:
682: # remove the last position in $binnum
683:
684: chop "$binnum"
685:
686: binnum="$rval"
687:
688: weight=`expr "$weight" "*" 2`
689:
690: done
691:
692: echo "binary $binnumorig is decimal $sum"
693:
694: 该脚本使用的算法是利用十进制和二进制数权值 (1,2,4,8,16,..),比如二进制"10"可以这样转换成十进制:
695:
696: 0 * 1 + 1 * 2 = 2
697:
698: 为了得到单个的二进制数我们是用了lastchar 函数。该函数使用wc –c计算字符个数,然后使用cut命令取出末尾一个字符。Chop函数的功能则是移除最后一个字符。
699:
700: 文件循环程序
701:
702: 或许您是想将所有发出的邮件保存到一个文件中的人们中的一员,但是在过了几个月
703:
704: 以后,这个文件可能会变得很大以至于使对该文件的访问速度变慢。下面的 脚本rotatefile
705:
706: 可以解决这个问题。这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,
707:
708: 而对于outmail.1就变成了outmail.2 等等等等...
709:
710: #!/bin/sh
711:
712: # vim: set sw=4 ts=4 et:
713:
714: ver="0.1"
715:
716: help()
717:
718: {
719:
720: cat <
721:
722: rotatefile -- rotate the file name
723:
724: USAGE: rotatefile [-h] filename
725:
726: OPTIONS: -h help text
727:
728: EXAMPLE: rotatefile out
729:
730: This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1
731:
732: and create an empty out-file
733:
734: The max number is 10
735:
736: version $ver
737:
738: HELP
739:
740: exit 0
741:
742: }
743:
744: error()
745:
746: {
747:
748: echo "$1"
749:
750: exit 1
751:
752: }
753:
754: while [ -n "$1" ]; do
755:
756: case $1 in
757:
758: -h) help;shift 1;;
759:
760: --) break;;
761:
762: -*) echo "error: no such option $1. -h for help";exit 1;;
763:
764: *) break;;
765:
766: esac
767:
768: done
769:
770: # input check:
771:
772: if [ -z "$1" ] ; then
773:
774: error "ERROR: you must specify a file, use -h for help"
775:
776: fi
777:
778: filen="$1"
779:
780: # rename any .1 , .2 etc file:
781:
782: for n in 9 8 7 6 5 4 3 2 1; do
783:
784: if [ -f "$filen.$n" ]; then
785:
786: p=`expr $n + 1`
787:
788: echo "mv $filen.$n $filen.$p"
789:
790: mv $filen.$n $filen.$p
791:
792: fi
793:
794: done
795:
796: # rename the original file:
797:
798: if [ -f "$filen" ]; then
799:
800: echo "mv $filen $filen.1"
801:
802: mv $filen $filen.1
803:
804: fi
805:
806: echo touch $filen
807:
808: touch $filen
809:
810: 这个脚本是如何工作的呢?在检测用户提供了一个文件名以后,我们进行一个9到1的循环。文件9被命名为10,文件8重命名为9等等。循环完成之后,我们将原始文件命名为文件1同时建立一个与原始文件同名的空文件。
811:
812: 调试
813:
814: 最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因。Shell程序的好处在于不需要重新编译,插入一个echo命令也不需要多少时间。
815:
816: shell也有一个真实的调试模式。如果在脚本"strangescript" 中有错误,您可以这样来进行调试:
817:
818: sh -x strangescript
819:
820: 这将执行该脚本并显示所有变量的值。
821:
822: shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:
823:
824: sh -n your_script
825:
826: 这将返回所有语法错误。
827:
828: 下面是测试语句的参数:
829: [ -a FILE ] 如果 FILE 存在则为真。
830: [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。
831: [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。
832: [ -d FILE ] 如果 FILE 存在且是一个目录则为真。
833: [ -e FILE ] 如果 FILE 存在则为真。
834:
835: [ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
836: [ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。
837: [ -h FILE ] 如果 FILE 存在且是一个符号连接则为真。
838: [ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。
839: [ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。
840: [ -r FILE ] 如果 FILE 存在且是可读的则为真。
841: [ -s FILE ] 如果 FILE 存在且大小不为0则为真。
842: [ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。
843: [ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。
844: [ -w FILE ] 如果 FILE 如果 FILE 存在且是可写的则为真。
845: [ -x FILE ] 如果 FILE 存在且是可执行的则为真。
846: [ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
847: [ -G FILE ] 如果 FILE 存在且属有效用户组则为真。
848: [ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
849: [ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。
850: [ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
851: [ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。
852: [ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
853: [ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。
854: [ -o OPTIONNAME ] 如果 shell选项 “OPTIONNAME” 开启则为真。
855: [ -z STRING ] “STRING” 的长度为零则为真。
856: [ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。
857: [ STRING1 == STRING2 ] 如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。
858: [ STRING1 != STRING2 ] 如果字符串不相等则为真。
859: [ STRING1 < STRING2 ] 如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。
860: [ STRING1 > STRING2 ] 如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。
861: [ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.
862:
863: UNIX Shell 里面比较字符写法:
864:
865: -eq 等于
866: -ne 不等于
867: -gt 大于
868: -lt 小于
869: -le 小于等于
870: -ge 大于等于
871: -z 空串
872: = 两个字符相等
873: != 两个字符不等
874: -n 非空串
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
阅读(806) | 评论(0) | 转发(0) |