zoukankan      html  css  js  c++  java
  • bash shell笔记2 结构化命令

    二、使用结构化命令
    知识内容:
    # 改变命令流
    # 使用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

  • 相关阅读:
    hadoop 3.0.0 alpha3 安装、配置
    集群使用初步
    转 mysql 中sql 语句查询今天、昨天、7天、近30天、本月、上一月 数据
    java 内存溢出
    获取手机上安装的应用信息
    使apk具有system权限
    Android基础之sqlite 数据库简单操作
    转 Android:文件下载和写入SD卡学习小结
    Android判断Service是否运行
    Android 定时重复启动弹出窗口。
  • 原文地址:https://www.cnblogs.com/songfeixiang/p/3733761.html
Copyright © 2011-2022 走看看