test和case那些不为人知的故事
2013-11-28 15:37
543 查看
最近在学习shell时发现虽然我经常使用test和case,但是它们仍然有许多不为人知的秘密。
首先来看test两个test
在linux中有两个test命令,一个是作为shell的内置命令,它是一个程序;另一个一般是磁盘的/usr/bin/test命令,但他一般不会被调用,因为首先找到的是shell的内置命令。 此外,test的另一个名称是[ 。 当调用[ 时,它需要一个] 作为其参数,但是如果不使用],[ 也能起到同样的作用。
常用的测试标志
-e 是否存在;
-s 是否存在且不为空;
-f 是否为常规文件;
-b 是否为块设备(块设备的驱动对象是像磁盘这样的按块进行操作的设备);
-c 是否为字符设备(字符设备的驱动对象可以向其读写字符的设备,如终端 );
-L(-h) 是否为符号链接;
-(rwx) 是否具有相应的权限,
8. -O(-G) 是否属于当前用户和/或组ID; 9. -u(-g) 是否具有suid或sgid(suid位与sgid位允许程序以文件所属用户(或组)的身份运行,而不一定是运行程序的用户(组) );
10. -N标志检测文件自从上次读取之后是否被修改。
-ef比较两个文件是否为同一文件系统中相同inode节点的硬链接。
需要注意的是: <和>只能在复合命令[[ ... ]]中起作用; ==和=!可以在单方括号和双括号中起作用; =只能在单括号中起作用;导致这种复杂性的原因是为了在添加更加强大的[[命令的同时,保持与Bourne shell的兼容性。
参数:
-z 测试在字符串长度为0时返回真,-n 在字符串长度非零时返回真。因为测试的字符串可能为空,所以需要用引号将变量名引用起来:否则[ -z $input ]就会成为[ -z ],这是错的,只有[ -z "$input" ]才是合法的。
参数: =~ 它将右边当作扩展的正则表达式,故可以通过[[ $pkgname =~ .*\.deb ]] 来查找匹配模式*.deb的文件名。注意要使用[[ ... ]]
常用参数: -eq 相等返回真; -ne 不相等返回真; -lt 小于返回真; -gt 大于返回真; -le 小于等于返回真; -ge 大于等于返回真;
使用&&和||操作符来将测试组合
再来看case对于case很多人都了解,但是关于用 ;; , ;;& 和 ;&来终止语句,你了解吗?;; 表示不再执行其他语句;;;& 表示还要匹配接下来的所有模式;;& 表示接下来的模式已经匹配;
首先来看test两个test
在linux中有两个test命令,一个是作为shell的内置命令,它是一个程序;另一个一般是磁盘的/usr/bin/test命令,但他一般不会被调用,因为首先找到的是shell的内置命令。 此外,test的另一个名称是[ 。 当调用[ 时,它需要一个] 作为其参数,但是如果不使用],[ 也能起到同样的作用。
[root@localhost ~]# type test; type [ test is a shell builtin [ is a shell builtin [root@localhost ~]# which test; which [ /usr/bin/test /usr/bin/[从中可以看到,在shell中,[是程序,而]只是[所需要的参数。
常用的测试标志
-e 是否存在;
-s 是否存在且不为空;
-f 是否为常规文件;
-b 是否为块设备(块设备的驱动对象是像磁盘这样的按块进行操作的设备);
-c 是否为字符设备(字符设备的驱动对象可以向其读写字符的设备,如终端 );
-L(-h) 是否为符号链接;
-(rwx) 是否具有相应的权限,
8. -O(-G) 是否属于当前用户和/或组ID; 9. -u(-g) 是否具有suid或sgid(suid位与sgid位允许程序以文件所属用户(或组)的身份运行,而不一定是运行程序的用户(组) );
[root@localhost ~]# cat suid.sh #!/bin/bash while read -p "What file do you want to test? :" filename do if [ ! -e "$filename" ]; then echo "The file does not exists." continue fi #Okey, the file exists ls -ld $filename if [ -u $filename ]; then echo " $filename will run as user \"`stat --printf=%U $filename`\"" fi if [ -g $filename ]; then echo "$filename will run as group \"`stat --printf=%G $filename`\"" fi done
10. -N标志检测文件自从上次读取之后是否被修改。
[root@localhost ~]# echo hello > /tmp/myfile.log [root@localhost ~]# echo hello world >> /tmp/myfile.log [root@localhost ~]# cat watchfile.sh #!/bin/bash GAP=10 # how long to wait LOGFILE=$1 # file to log to # Get the current length of the file. len=`wc -l $LOGFILE | awk '{ print $1 }'` echo "Current size is $len lines" while : do if [ -N $LOGFILE ]; then echo "`date`: New entries in $LOGFILE:" newlen=`wc -l $LOGFILE | awk '{ print $1 }'` newlines=`expr $newlen - $len` tail -$newlines $LOGFILE len=$newlen fi sleep $GAP done文件比较测试
-ef比较两个文件是否为同一文件系统中相同inode节点的硬链接。
[root@localhost ~]# cat equalfile.sh #!/bin/bash file1=$1 file2=$2 ls -il $file1 $file2 if [ $file1 -ef $file2 ]; then echo "$file1 is the same file as $file2" else echo "$file1 is not the same file as $file2" diff -q $file1 $file2 if [ "$?" -eq "0" ]; then echo "However, their contents are identical." fi fi [root@localhost ~]# echo testing > file1 [root@localhost ~]# ln file1 file2 [root@localhost ~]# echo testing > file3 [root@localhost ~]# ls -il file? 131679 -rw-r--r--. 2 root root 8 Nov 28 05:42 file1 131679 -rw-r--r--. 2 root root 8 Nov 28 05:42 file2 131995 -rw-r--r--. 1 root root 8 Nov 28 05:42 file3 [root@localhost ~]# sh equalfile.sh file1 file2 131679 -rw-r--r--. 2 root root 8 Nov 28 05:42 file1 131679 -rw-r--r--. 2 root root 8 Nov 28 05:42 file2 file1 is the same file as file2 [root@localhost ~]# sh equalfile.sh file1 file3 131679 -rw-r--r--. 2 root root 8 Nov 28 05:42 file1 131995 -rw-r--r--. 1 root root 8 Nov 28 05:42 file3 file1 is not the same file as file3 However, their contents are identical. [root@localhost ~]# echo something > file4 [root@localhost ~]# sh equalfile.sh file1 file4 131679 -rw-r--r--. 2 root root 8 Nov 28 05:42 file1 132003 -rw-r--r--. 1 root root 10 Nov 28 05:45 file4 file1 is not the same file as file4 Files file1 and file4 differ字符串比较测试可以测试字符串是否相等,以及按照字母表测试某个字符串是否排在另一个前面。
需要注意的是: <和>只能在复合命令[[ ... ]]中起作用; ==和=!可以在单方括号和双括号中起作用; =只能在单括号中起作用;导致这种复杂性的原因是为了在添加更加强大的[[命令的同时,保持与Bourne shell的兼容性。
参数:
-z 测试在字符串长度为0时返回真,-n 在字符串长度非零时返回真。因为测试的字符串可能为空,所以需要用引号将变量名引用起来:否则[ -z $input ]就会成为[ -z ],这是错的,只有[ -z "$input" ]才是合法的。
[root@localhost ~]# cat alnum.sh #!/bin/bash if [ "$1" = "$2" ]; then echo "$1 is the same as $2" else echo "$1 is not the same as $2" if [[ "$1" < "$2" ]]; then echo "$1 comes before $2" else echo "$1 comes after $2" fi fi [root@localhost ~]# sh alnum.sh apples bananas apples is not the same as bananas apples comes before bananas [root@localhost ~]# sh alnum.sh oranges oranges oranges is the same as oranges正则表达式测试
参数: =~ 它将右边当作扩展的正则表达式,故可以通过[[ $pkgname =~ .*\.deb ]] 来查找匹配模式*.deb的文件名。注意要使用[[ ... ]]
[root@localhost ~]# cat identify_pkgs.sh #!/bin/bash for pkg in pkgs/* do pkgname=`basename $pkg` echo $pkgname if [[ $pkgname =~ (.+)_(.*)_(.*)\.deb ]]; then echo "Package ${BASH_REMATCH[1]} Version ${BASH_REMATCH[2]} is a" echo " Debian package for the ${BASH_REMATCH[3]} architecture." echo elif [[ $pkgname =~ (.+)-(.+)\.(.*)\.rpm ]]; then echo "Package ${BASH_REMATCH[1]} Version ${BASH_REMATCH[2]} is an" echo " RPM for the ${BASH_REMATCH[3]} architecture." echo else echo "File \"$pkgname\" does not appear to match the" echo " standard .deb or .rpm naming conventions." fi done [root@localhost ~]# ls pkgs/ dbus-x11_1.2.24-4_and64.deb gnome-desktop-1.023.x86_64.rpm firmware-linux-free_2.6.32-29_all.deb libgnomeprint-2.18.6-2.6.x86_64.rpm [root@localhost ~]# sh identify_pkgs.sh dbus-x11_1.2.24-4_and64.deb Package dbus-x11 Version 1.2.24-4 is a Debian package for the and64 architecture. firmware-linux-free_2.6.32-29_all.deb Package firmware-linux-free Version 2.6.32-29 is a Debian package for the all architecture. gnome-desktop-1.023.x86_64.rpm Package gnome-desktop Version 1.023 is an RPM for the x86_64 architecture. libgnomeprint-2.18.6-2.6.x86_64.rpm Package libgnomeprint-2.18.6 Version 2.6 is an RPM for the x86_64 architecture.数值测试
常用参数: -eq 相等返回真; -ne 不相等返回真; -lt 小于返回真; -gt 大于返回真; -le 小于等于返回真; -ge 大于等于返回真;
[root@localhost ~]# cat numberguess.sh #!/bin/bash MAX=50 guess=-1 let answer=($RANDOM %$MAX) let answer+=1 ceiling=$MAX floor=0 guesses=0 while [ "$guess" -ne "$answer" ] do echo "The magic number is between $floor and $ceiling." echo -en " Make your guess:" read guess guesses=`expr $guesses + 1` if [ "$guess" -lt "$answer" ]; then echo "$guess is too low" if [ "$guess" -ge "$floor" ]; then floor=`expr $guess + 1` fi fi if [ "$guess" -gt "$answer" ]; then echo "$guess is too high" if [ "$guess" -lt "$ceiling" ]; then ceiling=`expr $guess - 1` fi fi done echo "You got it in $guesses guesses!" [root@localhost ~]# sh numberguess.sh The magic number is between 0 and 50. Make your guess:25 25 is too high The magic number is between 0 and 24. Make your guess:12 12 is too low The magic number is between 13 and 24. Make your guess:18 18 is too high The magic number is between 13 and 17. Make your guess:15 15 is too low The magic number is between 16 and 17. Make your guess:16 16 is too low The magic number is between 17 and 17. Make your guess:17 You got it in 6 guesses!组合测试
使用&&和||操作符来将测试组合
[root@localhost ~]# wc -l /etc/hosts || echo wc failed to read /etc/hosts 2 /etc/hosts [root@localhost ~]# wc -l /etc/hosts.bak || echo wc failed to read /etc/hosts wc: /etc/hosts.bak: No such file or directory wc failed to read /etc/hosts [root@localhost ~]# wc -l /etc/hosts | grep "^3" || echo /etc/hosts is 3 lines file /etc/hosts is 3 lines file [root@localhost ~]# wc -l /etc/hosts | grep "^2" && echo /etc/hosts is 2 lines file 2 /etc/hosts /etc/hosts is 2 lines file
再来看case对于case很多人都了解,但是关于用 ;; , ;;& 和 ;&来终止语句,你了解吗?;; 表示不再执行其他语句;;;& 表示还要匹配接下来的所有模式;;& 表示接下来的模式已经匹配;
[root@localhost ~]# cat case2.sh #!/bin/bash read -p "Which city are you closest to?:" city case $city in "New York"|London|Paris|Tokyo) echo "That is a capital city" ;;& Chicago|Detroit|"New York"|Washington) echo "you are in the USA" ;; London|Edinburgh|Cardiff|Dublin) echo "you are in the United Kingdom" ;; "Ramsey Street") echo "G'Day Netghbour!" ;& Melbourne|Canberra|Sydney) echo "you are in australai" ;; Paris) echo "you are in France" ;; Tokyo) echo "you are in Japan" ;; N*) echo "your word begins with N but is not New York!" ;; *) echo "I'm sorry, I don't konw anything about $city" ;; esac [root@localhost ~]# sh case2.sh Which city are you closest to?:London That is a capital city you are in the United Kingdom [root@localhost ~]# sh case2.sh Which city are you closest to?:Ramsey street I'm sorry, I don't konw anything about Ramsey street [root@localhost ~]# sh case2.sh Which city are you closest to?:Ramsey Street G'Day Netghbour! you are in australai
相关文章推荐
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断
- 谁是桌面王者?Win PK Linux三大镇山之宝
- vivi下重新调整分区
- Linux VS Unix:Linux欲一统天下 Unix不死
- linux下设定环境变量
- Linux下修改MySQL编码的方法
- Linux串口通信
- 从Windows系统下访问Linux分区相关软件
- 看看我的Ubuntu Linux截图
- ARM Linux系统启动
- Linux及ARM Linux程序开发笔记(零基础入门篇)