二、使用结构化命令

知识内容:

# 改变命令流

# 使用if-then逻辑

# 嵌套if-then

# 测试条件

# 高级if-then功能

许多程序在脚本命令之间需要某些逻辑控制流,有些命令允许脚本根据变量值的条件或者命令的结果跳过一些命令或者循环执行这些命令,这叫做结构化命令。

1、使用if-then语句

最基本的结构化命令类型就是if-then语句,其格式如下:

if command

then

command

fi

意思是说:if语句后面的命令的退出状态值是0,则执行then后面的所有命令;如果不是0则命令不执行。如下例子:

[root@wzp ~]# cat test2

#!/bin/bash

if date

then

echo "it works"

fi

[root@wzp ~]# ./test2

2011年 01月 28日 星期五 21:15:12 CST

it works
我们知道date命令是有效命令,查看$?肯定是0的,所以就执行then后的命令,这个应该不难理解。

2、if-then-else语句

这个语句可以提供一组命令,其格式如下:

if command

then

command

else

command

if

意思是说:if语句后面的命令的退出状态值是0,则执行then后面的所有命令;跟if-then一样,如果不是则执行else后面的命令。如下例子:
[root@wzp
~]# cat test2

#!/bin/bash

testuser=51cto

if grep $testuser /etc/passwd

then

echo  the files for $testuser are:

ls -a /home/$testuser/.*

else

echo the user name $testuser does not exist !

fi

[root@wzp ~]# ./test2

the user name 51cto does not exist !
从上面可以看到由于不存在51cto用户,则执行else后面的命令

但是当我创建了51cto用户,则:
[root@wzp
~]# useradd 51cto

[root@wzp ~]# ./test2

51cto:x:502:502::/home/51cto:/bin/bash

the files for 51cto are:

/home/51cto/.bash_logout  
/home/51cto/.bashrc

/home/51cto/.bash_profile 
/home/51cto/.emacs

/home/51cto/.:

.  .. 
.bash_logout  .bash_profile 
.bashrc  .emacs 
.mozilla

/home/51cto/..:

.  ..  51cto 
aa  bb 
lost+found

/home/51cto/.mozilla:

.  .. 
extensions  plugins
直接执行then后的命令!这个也容易理解!~

3、嵌套if语句

有时需要在脚本代码中检查几种情况,可以使用else的另一种版本叫elif,但是要嵌套许多if-then语句,后续有case命令介绍,这个更加的方便使用,这里就不对嵌套if语句详解了,其格式是:

if command

then

command

elif   
command

then

command

fi

4、test命令

这是一个重头戏,bash shell提供一种在if-then语句中声明test命令的另一种方法:

if [ condition ] 
//注意这里的condition两边有空格!切记!

then

command

fi

test命令能够评估以下3类命令:

# 数值比较

# 字符串比较

# 文件比较

下面就具体就test命令的用户逐一说明!!!

4.1、数值比较

如下式数值比较表:

**********************************************

n1  -eq 
n2   
检查n1是不是等于n2

n1  -ge 
n2   
检查n1是不是大于或等于n2

n1  -gt 
n2   
检查n1是否大于n2

n1  -le 
n2   
检查n1是否小于或等于n2

n1  -lt 
n2   
检查n1是否小于n2

n1  -ne 
n2   
检查n1是否不等于n2

**********************************************

下面看看一个例子:
[root@wzp
~]# cat test2

#!/bin/bash

num1=10

num2=11

if [ $num1 -gt 5 ]

then

echo the test value $num1 is greater than
5

fi

if [ $num2 -eq $num1 ]

then

echo  the values are
equal

else

echo  the values are
different

fi

[root@wzp ~]# ./test2

the test value 10 is greater than 5

the values are different
给num1和num2赋值,然后通过测试,得出不同结论,这个好理解!

4.2、字符串比较

test命令允许对字符串值进行比较,主要分为如下三种比较类型:

1、字符串是否相同

2、字符串顺序(大小)

3、字符串长度

首先也先看看test命令字符串比较表

********************************************

str1 = str2  
检查str1和str2是否相同

str1 != str2  检查str1和str2是否不同

str1 < str2  
检查str1是否小于str2

str1 > str2  
检查str1是否大于str2

-n
str1    
检查str1长度是否大于0

-z
str1    
检查str1长度是否为0

********************************************

下面对三种类型举个例子:

1)字符串是否相等

[root@wzp ~]# cat test2

#!/bin/bash

testuser=root

if [ $USER=$testuser ]

then

echo welcome $testuser

fi

[root@wzp ~]# ./test2

welcome root
可以看到字符串相等的显示效果
[root@wzp
~]# cat test2

#!/bin/bash

testuser=root

if [ $USER!=$testuser ]

then

echo this is not $testuser

else

echo welcome $testuser

fi

[root@wzp ~]# ./test2

this is not root
不相等的情况则显示then后的内容

2)字符串顺序
[root@wzp
~]# cat test2

#!/bin/bash

str1=aaa

str2=bbb

if [ $str1 > $str2 ]

then

echo $str1 is greater than $str2

else

echo $str1 is less than $str2

fi

[root@wzp ~]# ./test2

aaa is greater than bbb

[root@wzp ~]# ll aaa

-rw-r--r-- 1 root root 0 01-28 22:22 aaa
在脚本中单独使用了大于号>,虽然没报错,但结果是错误的,a打头肯定是小于b的。这个脚本把大于号理解成输出重定向,所以才出现这样的情况,我们可以通过转义大于号解决这个问题:
[root@wzp
~]# cat test2

#!/bin/bash

str1=aaa

str2=bbb

if [ $str1 \> $str2
]    
//此处添加一个\就行了

then

echo $str1 is greater than $str2

else

echo $str1 is less than $str2

fi

[root@wzp ~]# ./test2

aaa is less than bbb
这样就得出了正确的结果!

还有一点要说明的就是大小写的问题,它的顺序跟sort命令的顺序是相反的!test命令是通过ASCII数值来决定排列顺序的,这个稍微了解下就好。

3)字符串大小

评估一个变量是否包含数据,通过使用-n和-z比较很方便,如下例子:
[root@wzp
~]# cat test2

#!/bin/bash

str1=aaa

str2=

if [ -n $str1
]   
//长度是否大于0

then

echo the string $str1 is not empty

else

echo the string $str1 is empty

fi

if [ -z $str2
]    
//长度是否为0

then

echo the string $str2 is empty

else

echo the string $str2 is not empty

fi

if [ -z $str3
]    
//长度是否为0

then

echo the string $str3 is empty

else

echo the string $str3 is not empty

fi

[root@wzp ~]# ./test2

the string aaa is not empty

the string is empty

the string is empty
如上对于str1和str2应该没什么问题,而对于没有定义变量str3则认定其字符串为零。

4.3、文件比较

test命令能够检测linux文件系统上的文件状态和路径,对于文件比较这一块挺多东西的,下面一一道来,首先看看test命令文件比较表:

****************************************************************

-d file  
 检测file是否存在并且是一个目录

-e file 
  检测file是否存在

-f file   
检测file是否存在并且是一个文件

-r file 
  检测file是否存在并且刻度

-s file  
 检测file是否存在并且不为空

-w
file   检测file是否存在并且可写

-x file  
 检测file是否存在并且可执行

-O
file   检测file是否存在并且被当前用户拥有

-G
file         
检测file是否存在并且默认组是否为当前用户组

file1 -nt
file2  检测file1是否比file2新

file1 -ot
file2  检测file1是否比file2旧

*****************************************************************

对于上面这个表,如下通过10个例子说明:

1)检测目录
[root@wzp
~]# cat test2

#!/bin/bash

if [ -d $HOME ]

then

echo your home directory exists

cd $HOME

ls

else

echo there is someting wrong with your
HD

fi

[root@wzp ~]# ./test2

your home directory exists

aaa             
bbb     
install.log        
mbox  test2

anaconda-ks.cfg  Desktop 
install.log.syslog  one
使用-d把我这个root的家目录ls出来了~~

2)检测对象是否存在
[root@wzp
~]# cat test2

#!/bin/bash

if [ -e $HOME ]

then

echo   yes,
the HD exists

if [ -e $HOME/bbs.51cto ]

then

echo the
bbs.51cto exists

else

touch
$HOME/bbs.51cto

echo
creating new file name bbs.51cto

fi

fi
从上面我们看到目录肯定是存在的,我的root嘛,但是这个bbs.51cto是不存在的,所以第一次执行文件显示不存在,并且私下创建了。
[root@wzp
~]# ./test2

yes, the HD exists

creating new file name bbs.51cto
第二次执行文件那肯定是显示存在bbs.51cto了,呵呵
[root@wzp
~]# ./test2

yes, the HD exists

the bbs.51cto exists
3)检测文件

-e适合用于检测文件和目录,要确定对象是文件,使用-f比较,下例:
[root@wzp
~]# cat test2

#!/bin/bash

if [ -e $HOME ]

then

echo the $HOME exists !

if [ -f $HOME ]

then

echo yes, it
is a file

else

echo no, it
is not a file

if [ -f $HOME/.bash_history ]

then

echo but $HOME/.bash_history is a file

else

echo it is not a file too

fi

fi

else

echo there is not object!

fi

[root@wzp ~]# ./test2

the /root exists !

no, it is not a file

but /root/.bash_history is a file
上面的例子应该很好懂,注意-f是检测文件,-e可以检测文件和目录就行了!

4)检测是否可读

通过-r可检测可读性,如下例:
[51cto@wzp
~]$ whoami

51cto

[51cto@wzp ~]$ cat test

#!/bin/bash

testfile=/etc/shadow

if [ -f $testfile ]

then

if [ -r $testfile ]

then

ls -l
$testfile

else

echo "i'm
unable to read the file"

fi

else

echo "the file doesn't exist"

fi

[51cto@wzp ~]$ sh test

i'm unable to read the file

[51cto@wzp ~]$ su - root

口令:

[root@wzp ~]# sh /home/51cto/test

-r-------- 1 root root 1204 01-28 21:27 /etc/shadow
如上可知普通用户51cto无法读取文件。

5)检测空文件

通过-s检测文件是否为空,例子如下:
[root@wzp
~]# cat test2

#!/bin/bash

file=testfile

touch $file

if [ -s $file ]

then

echo the file exists and has data in
it

else

echo the file exists but empty

fi

date > $file

if [ -s $file ]

then

echo the file exists and has data in
it

else

echo the file exists but empty

fi

[root@wzp ~]# ./test2

the file exists and has data in it

the file exists and has data in it
先是创建空文件,然后通过重定向date进去判断文件不为空,这个好理解!

6)检测是否能够可写

通过-w检测文件是否可写,例子如下:
[root@wzp
~]# cat test2

#!/bin/bash

file=$HOME/testfile

touch $file

chmod u-w $file

now='date +%y%m%d-%H%M'

if [ -w $file ]

then

echo the file could be written

else

echo "the file couldn't be written"

fi

chmod u+w $file

if [ -w $file ]

then

echo the file could be written

$now > $HOME/testfile

echo  and the file views
$file

else

echo "the file couldn't be written"

fi

[root@wzp ~]# ./test2

the file could be written

the file could be written

and the file views /root/testfile

[root@wzp ~]# cat /root/testfile

110129-1317
上面的例子相等好理解,没什么好说的。

7)检测是否能运行文件

通过-x可以检测文件是否可被执行,如下例:
[root@wzp
~]# cat test2

#!/bin/bash

file=$HOME/testfile2

touch $file

chmod u+x $file

if [ -x $file ]

then

echo the file could be run

else

echo "the file couldn't be run"

fi

[root@wzp ~]# ./test2

the file could be run

[root@wzp ~]# ll testfile2

-rwxr--r-- 1 root root 0 01-29 13:21 testfile2
这个也没什么疑惑之处。

8)检测所有者

通过-O可以检测你是否属于这个文件的所有者,如下例:
[root@wzp
~]# cat test2

#!/bin/bash

file=/etc/passwd

if [ -O $file ]

then

echo "you are the owner of the $file"

else

echo "you aren't the owner of the
$file"

fi

[root@wzp ~]# ./test2

you are the owner of the /etc/passwd

[root@wzp ~]# ll /etc/passwd

-rw-r--r-- 1 root root 1877 01-28 21:27 /etc/passwd
/etc/passwd属有者肯定是root啦!

9)检测所属组

-G检测文件的默认组,如果它跟当前用户的默认组匹配,则检测成功,如下例:
[root@wzp
~]# cat test2

#!/bin/bash

file=/etc/passwd

if [ -G $file ]

then

echo "you are in the same group as
$file"

else

echo "you aren't in the same group as the
$file"

fi

[root@wzp ~]# ./test2

you are in the same group as /etc/passwd

[root@wzp ~]# ll -d /etc/passwd

-rw-r--r-- 1 root root 1877 01-28 21:27 /etc/passwd
很明显,/etc/passwd肯定属于root组咯
[root@wzp
~]# chgrp 51cto /etc/passwd

[root@wzp ~]# ll -d /etc/passwd

-rw-r--r-- 1 root 51cto 1877 01-28 21:27 /etc/passwd

[root@wzp ~]# ./test2

you aren't in the same group as the /etc/passwd
当把这个文件的所属组改成51cto后,则检测不成功了,不过现实中别做这样的修改

10)检测文件日期

一般通过-nt和-ot来比较两个文件之间的新旧,这里指的是创建或修改日期,例子:
[root@wzp
~]# ll aa bb

-rw-r--r-- 1 root root 0 01-29 13:41 aa

-rw-r--r-- 1 root root 0 01-29 14:23 bb

aa

[root@wzp ~]# cat test2

#!/bin/bash

if [ $HOME/aa -nt $HOME/bb ]

then

echo the aa is newer than bb

else

echo the aa is older than bb

fi

[root@wzp ~]# ./test2

the aa is older than bb
下面我把aa文件修改下内容:
[root@wzp
~]# vim aa

[root@wzp ~]# ll aa bb

-rw-r--r-- 1 root root 3 01-29 14:28 aa

-rw-r--r-- 1 root root 0 01-29 14:23 bb

[root@wzp ~]# ./test2

the aa is newer than bb
这个结果应该很容易接受!

OKOK,到这里test命令的内容就结束了,如上各种类型比较得以说明了。

5、复合条件检测

if-then语句可以使用布尔逻辑来合并检测条件,格式:

*****************************************************

[ condition ] && [ condition
]   这个表示逻辑与 and

[ condition ] || [ condition ]  
这个表示逻辑或 or

*****************************************************

如下例子:
[root@wzp
~]# cat test2

#!/bin/bash

if [ -d $HOME ] && [ -w $HOME/wzp ]

then

echo the file exists and you can wirte
$HOME/wzp

else

echo "you can't write the file"

fi

if [ -d $HOME ] || [ -w $HOME/wzp ]

then

echo the file exists and you can wirte
$HOME/wzp

else

echo "you can't write the file"

fi

[root@wzp ~]# ./test2

you can't write the file

the file exists and you can wirte /root/wzp

[root@wzp ~]# ll /root/wzp
ls:
/root/wzp: 没有那个文件或目录
$HOME是root家目录,肯定存在的,但是不存在文件/root/wzp

6、if-then的高级特征

既然说是高级特征,必然作用非凡了,呵呵

其功能体现是通过双圆括号(())表示数学表达式和双方括号[[]]表示高级字符串处理函数。

6.1、使用双圆括号

先看一个例子:
[root@wzp
~]# cat test2

#!/bin/bash

num1=10

if (( $num1 ** 2 > 90 ))

then

(( num2=$num1 ** 2 ))

echo the square of $num1 is $num2

fi

[root@wzp ~]# ./test2

the square of 10 is 100
这里的**表示取幂,由此可见(())可以很方便处理数学表达式

6.2、使用双方括号

使用双方括号可以定义与字符串值相匹配的正则表达式,如例:
[root@wzp
~]# cat test2

#!/bin/bash

if [[ $USER == r* ]]

then

echo  hello $USER

else

echo sorry , i "don't" know you

fi

[root@wzp ~]# ./test2

hello root

[root@wzp ~]# cp test2 /home/51cto/

[root@wzp ~]# su - 51cto

[51cto@wzp ~]$ sh test2

sorry , i don't know you
这里用到了通配符*,表示r开头的任何用户,正则表达式的内容放置后面说明!
[root@wzp
~]# useradd rrr

[root@wzp ~]# cp test2 /home/rrr

[root@wzp ~]# su - rrr

[rrr@wzp ~]$ sh test2

hello rrr
这都好理解吧~~~

7、case命令

还记得前面提及到case命令吧,当在一组可能的值中寻找特定的值,可以写if-then-else语句,其中嵌套elif语句继续着if-then检测,这样子就很冗长麻烦。所以可以通过case命令简化,以列表导向格式检测单个变量的多个值,格式为:

case xxx in

xx | xx) command;

xx) command;

*) default command;

esac

下面通过一个例子:
[root@wzp
~]# cat test2

#!/bin/bash

case $USER in

root | testuser)

echo welcome $USER

echo your are admin;;

51cto)

echo welcome $USER;;

*)

echo welcome $USER;;

esac

[root@wzp ~]# ./test2

welcome root

your are admin

[root@wzp ~]# cp test2 /home/51cto/

cp:是否覆盖“/home/51cto/test2”? y

[root@wzp ~]# su - 51cto

[51cto@wzp ~]$ sh test2

welcome 51cto
判断是root和51cto用户则显示特定内容,如果通过其他用户执行,如下:
[root@wzp
~]# useradd testuser24

[root@wzp ~]# cp test2 /home/testuser24/

[root@wzp ~]# su - testuser24

[testuser24@wzp ~]$ sh test2

welcome testuser24
这个都比较好理解吧,假设通过存在的用户testuser执行,那显示的内容肯定是:

welcome testuser

your are admin

哈哈,说是admin也不正确了。

好了,对于部分结构化命令就说到这里,后续是循环、迭代等结构化命令的讲述。

本文出自 “twenty_four
博客,请务必保留此出处http://twentyfour.blog.51cto.com/945260/505654

bash&nbsp;shell笔记2&nbsp;结构化命令的更多相关文章

  1. bash&nbsp;shell笔记3&nbsp;结构化命令二

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/513601 三 ...

  2. shell脚本编程-使用结构化命令(if/else)(转)

    11.1 使用if-then语句 格式如下 if语句会执行if行定义的那个命令,如果该命令的退出状态码是0,则then部分的语句就会执行,其他值,则不会   1 2 3 4 if command th ...

  3. 学习笔记:CentOS7学习之二十二: 结构化命令case和for、while循环

    目录 学习笔记:CentOS7学习之二十二: 结构化命令case和for.while循环 22.1 流程控制语句:case 22.2 循环语句 22.1.2 for-do-done 22.3 whil ...

  4. linux shell脚本使用结构化命令

    内容: 一.if-then命令 二.if-then-else命令 三.test命令 四.case命令 1.if-then结构化命令中最基本的类型,其格式如下: if command then comm ...

  5. Shell 语法之结构化命令(流程控制)

    许多程序在脚本命令之间需要某种逻辑流控制,允许脚本根据变量值的条件或者其他命令的结果路过一些命令或者循环执行这些命令.这些命令通常被称为结构化命令.和其他高级程序设计语言一样,shell提供了用来控制 ...

  6. 《Linux命令行与shell脚本编程大全》第十二章 使用结构化命令

    许多程序要就对shell脚本中的命令施加一些逻辑控制流程. 结构化命令允许你改变程序执行的顺序.不一定是依次进行的 12.1 使用if-then语句 如下格式: if command then     ...

  7. shell的结构化命令

    shell在逻辑流程控制这里会根据设置的变量值的条件或其他命令的结果跳过一些命令或者循环执行的这些命令.这些命令通常称为结构化命令 1.if-then语句介绍 基本格式 if command then ...

  8. bash&nbsp;shell笔记1&nbsp;脚本基础知识

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/505644 * ...

  9. shell脚本之结构化命令if...then...fi

    if的用法日常主要用于数值或者字符串的比较来实现结构化的,模拟人脑,就是如果遇到什么事情,我们应该做什么 语法格式分为 1. if command;then command;fi    (如果if满足 ...

随机推荐

  1. selenium webdriver入门

    写在前面:最近在研究UI自动化测试的过程中,发现公司里通常用的是AutomanX框架,而这个框架实际上是基于selenium webdriver框架的,所以在编写测试用例时,很多语法都是直接使用sel ...

  2. Dojo Chart之常用统计图

    很多做web的都知道,在很多web系统中会涉及到一些统计图,例如饼状图,柱状图.趋势图.以及叠加图等.提到这儿,做web的都很熟悉的,jquery的highcharts就能搞定所有的涉及到统计图的功能 ...

  3. 【MFC】MFC改变对话框中静态文本的字体大小

    MFC改变对话框中静态文本的字体大小 2010/08/09 11:30 VC的对话框字体设置对所有控件都有效,你不能单独地改变某个静态文本的字体.对于你的问题,需要首先用CreateFont来建立一个 ...

  4. centos7怎么把语言切换成英语

    一.简介 在Linux的系统中经常碰到字符集导致的错误,本文总结了设置修改系统语言环境的方法步骤. 二.操作步骤 执行如下指令,查看当前使用的系统语言 echo $LANG 执行如下指令,查看系统安装 ...

  5. SQL—数据分析

    留存分析——左连接 矩阵分析——group by 结构分析:分析每种产品占据总销售量的比例 排序分析

  6. TypeError: parse() got an unexpected keyword argument 'transport_encoding' 安装tensor后报错

    TypeError: parse() got an unexpected keyword argument 'transport_encoding' 巨蛋疼,出这个问题后,老夫真是醉了,mmp,最后在 ...

  7. LOJ10042 收集雪花

    题意 不同的雪花往往有不同的形状.在北方的同学想将雪花收集起来,作为礼物送给在南方的同学们.一共有 n 个时刻,给出每个时刻下落雪花的形状,用不同的整数表示不同的形状.在收集的过程中,同学们不希望有重 ...

  8. gulp 流处理

    包含的内容:     穿插流     流合并     流队列     流筛选 1. 穿插流 // passthrough stream 把流传递给其他的 // use gulp.src(glob,{p ...

  9. mybatis排序

    排序的时候#和$的分别 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by ...

  10. 使用内部变量,删除,替换,UNSET,等字符操作

    使用内部变量,删除,替换,UNSET,等字符操作 FREDDY=freddy   删除字符串前几2个字符: [root@localhost tmp]# echo ${FREDDY:2} eddy   ...