zoukankan      html  css  js  c++  java
  • linux bash算术运算和条件语句

    +, -, *(乘), /(除), **(乘方), %(取模)

    • let var=算术运算符表达式

      高级let用法:let i+=2

      +=,-=,*=,/=,%=,**=

      自增:let var++

    • var=$[算术运算符表达式]

    • var=$((算术运算符表达式))

    • var=$(expr $ARG1 OP $APG2)

    </font color=red>注意:乘法符号在某些场景中需要使用转义符

    练习1:写一个脚本文件,完成如下功能:添加3个用户,求这3个用户的UID之和。

    #!/bin/bash
    
    id testUser1 > /dev/null || useradd testUser1
    id testUser2 > /dev/null || useradd testUser2
    id testUser3 > /dev/null || useradd testUser3
    
    uid1=`grep "testUser1" /etc/passwd | cut -d: -f3`
    uid2=`grep "testUser2" /etc/passwd | cut -d: -f3`
    uid3=$(grep "testUser3" /etc/passwd | cut -d: -f3)
    
    #方法1
    #let num=$uid1+$uid2+$uid3
    #方法2
    #num=$[$uid1+$uid2+$uid3]
    #方法3
    num=$(($uid1+$uid2+$uid3))
    #方法4
    #num=$(expr $uid1 + $uid2 + $uid3)
    echo $num
    
    

    练习2:写一个脚本文件,完成如下功能:求/etc/passwd文件中第10行和第20行的用户的UID之和

    #!/bin/bash
    
    #先用head取前10行,再用tail取最好一行,然后再用cut切
    la=`head -10 /etc/passwd | tail -1 | cut -d: -f3`
    lb=`head -20 /etc/passwd | tail -1 | cut -d: -f3`
    
    echo $la
    echo $lb
    
    let lc=$la+$lb
    echo $lc
    

    练习3:写一个脚本文件,完成如下功能:求/etc/passwd文件中,uid最大的2个uid之和

    #!/bin/bash
    
    #先用冒号把文件分成多列,用第三列从大到小排序后,分别取第一行和第二行,最后在用cut切开
    la=`sort -t: -k3 -nr /etc/passwd | head -1 | cut -d: -f3`
    lb=`sort -t: -k3 -nr /etc/passwd | head -2 | tail -1 | cut -d: -f3`
    
    echo $la
    echo $lb
    
    let lc=$la+lb
    echo $lc
    

    练习4:写一个脚本文件,完成如下功能:通知2个文件里的空白行数之和

    #!/bin/bash
    
    #用grep找出空白行(使用正则表达式),然后再用wc数一数有多少行
    la=`grep -e "^[[:space:]]*$" /etc/rc.d/init.d/functions | wc -l`
    lb=`grep -e "^[[:space:]]*$" /etc/inittab | wc -l`
    
    echo $la
    echo $lb
    
    let lc=$la+$lb
    echo $lc
    

    条件语句

    测试表达式:

    • test expression
    • [ expression ]
    • [[ expression ]]

    注意:中括号中间的空格,没有空格就是语法错误

    bash的条件测试类型

    • 数值比较大小

      • -eq:等于 [ $num1 -eq $num2 ]
      • -ne:不等于[ $num1 -ne $num2 ]
      • -gt:大于[ $num1 -gt $num2 ]
      • -ge:大于等于[ $num1 -ge $num2 ]
      • -lt:小于[ $num1 -lt $num2 ]
      • -le:小于等于[ $num1 -le $num2 ]

      例子:[ 2 -ne 3 ]和test 2 -ne 3效果一样

      #!/bin/bash
      
      if [ 2 -ne 3 ]; then
          echo 11
      else
          echo 22
      fi
      
      if test 2 -ne 3; then
          echo 111
      else
          echo 222
      fi
      
    • 字符串比较

      == :等于

      > :大于

      < :小于

      != :不等于

      =~ :左侧字符串是否被右侧的正则表达式所匹配。

      -z "STRING" :指定字符串为空则为真

      -n "STRING":指定字符串不为空则为真

      做字符串比较的变量,最好加上“”。不加的话,如果做比较的某个变量没有被定义的话,执行就会出错。

      下面的例子,tom是不存在的变量,不加括号就出错误了,加了就没有错误。

      $ [ tom = $tom ]
      -bash: [: tom: unary operator expected
      $ [ tom = "$tom" ]
      $ echo $?
      1
      

      字符串比较,最好要用[[]]。

      下面的例子,说明了用[]无法比较

      $ [ a > b ]
      $ echo $?
      0
      $ [ a < b ]
      $ echo $?
      0
      $ [ "a" < "b" ]
      $ echo $?
      0
      $ [ "a" > "b" ]
      $ echo $?
      0
      

      下面的例子,说明用[[ ]]达到了预期。

      $ [[ a < b ]]
      $ echo $?
      0
      $ [[ a > b ]]
      $ echo $?
      1
      $ [[ "a" > "b" ]]
      $ echo $?
      1
      $ [[ "a" < "b" ]]
      $ echo $?
      0
      

      字符串空的判断:

      $ [[ -z "$tom" ]]
      $ echo $?
      1
      [ys@localhost ~]$ [[ -n "$tom" ]]
      [ys@localhost ~]$ echo $?
      
      

      正则表达式的匹配:

      $ tom=ooo
      [ys@localhost ~]$ [[ $tom =~ o.* ]]
      [ys@localhost ~]$ echo $?
      0
      [ys@localhost ~]$ tom=jerry
      [ys@localhost ~]$ [[ $tom =~ o.* ]]
      [ys@localhost ~]$ echo $?
      1
      
    • 文件测试

      • 文件存在性检查:-a FILE,或者,-e FILE。存在返回0.

        例子:[ -a /etc/passwd ][ -e /etc/passwd ]

      • 文件存在性和类型检查

        -b FILE:文件存在,且类型是块设备,则返回0.

        -c FILE:文件存在,且类型是字符设备,则返回0.

        -d FILE:文件存在,且类型是目录,则返回0.

        -f FILE:文件存在,且类型是普通文件,则返回0.

        -h或 -L FILE:文件存在,且类型是符号链接,则返回0.

        -p FILE:文件存在,且类型是命名管道,则返回0.

        -S FILE:文件存在,且类型是本地套接字,则返回0.

        $ [ -b /dev/sda ]
        [ys@localhost scripts]$ echo $?
        0
        [ys@localhost scripts]$ [ -b /dev/sdad ]
        [ys@localhost scripts]$ echo $?
        1
        [ys@localhost scripts]$ [ -b 2.sh ]
        [ys@localhost scripts]$ echo $?
        1
        
      • 文件权限检查

        -r FILE:文件存在,且当前用户(运行此shell进程的用户)可读,则返回0.

        -w FILE:文件存在,且当前用户(运行此shell进程的用户)可写,则返回0.

        -x FILE:文件存在,且当前用户(运行此shell进程的用户)可执行,则返回0.

      • 特殊权限检查

        -u FILE:文件存在,且拥有suid权限,则返回0.

        -g FILE:文件存在,且拥有sgid权限,则返回0.

        -k FILE:文件存在,且拥有sticky权限,则返回0.

      • 文件是否有内容

        -s FILE:文件存在,且有内容,则返回0

      • 时间戳

        -N FILE:文件自从上一次读取操作后,是否被修改过。

      • 从属关系

        -O FILE:当前用户是否文件属主

        -G FILE:当前用户是否在文件属组里。

      • 双目

        FILE1 -ef FILE2:如果FILE1和FILE2是指向同一个文件系统的相同inode的硬链接,则返回0.

        FILE1 -nt FILE2:如果FILE1的修改时间戳新于FILE,则返回0

        FILE 1 -ot FILE2:如果FILE1的修改时间戳旧于FILE,则返回0

    组合测试条件

    第一种方式:

    • [ expression1 ] && [ expression2 ]
    • [ expression1 ] || [ expression2 ]
    • ! COMMOND

    第二种方式:

    • 与运算:[ expression1 -a expression2 ]
    • 或运算:[ expression1 -o expression2 ]

    练习:判断主机名称是否为空,或者是否是localhost.localdomain

    #!/bin/bash
    
    hostname=`hostname`
    if [ -z "$hostname" -o "$hostname" == "localhost.localdomain" ]; then
        hostname=11111
    else
        echo "ng"
    fi
    echo $hostname
    

    向脚本文件传递执行时候的参数

    使用位置参数变量:$1,$2,...${10},${11}.

    10之后的参数必须加上{}。

    $0:是脚本本身的路径加脚本文件的名字。

    $#:是参数的个数

    $*:拿到所有参数。但把所有参数汇总成了一个串

    $@:拿到所有参数。但没有把参数汇总成一个串。

    当执行下面命令后,$1的值就是111;$2的值就是222;$3的值就是333;

    $ ./script.sh 111 222 333
    

    shift用法:shift n:踢掉前n个位置参数变量

    下面的内容保存在shift.sh中

    #!/bin/bash
    echo $1 $2
    shift 1
    echo $1
    shift 1
    echo $1
    

    执行shift.sh的结果:

    # bash shift.sh 111 222 333
    111 222
    222
    333
    

    练习:传递2个文本文件的路径给脚本,计算出空白行数之和。

    #!/bin/bash
    la=`grep -e "^[[:space:]]*$" $1 | wc -l`
    lb=`grep -e "^[[:space:]]*$" $2 | wc -l`
    echo $la
    echo $lb
    
    let lc=$la+$lb
    echo $lc
    

    执行结果:

    # bash sumforarg.sh /etc/rc.d/init.d/functions /etc/inittab
    91
    0
    91
    

    if语法

    if  con1 ; then
    
    elif con2 ; then
    
    else
    
    fi
    

    练习:查看给定用户是否存在,不存在则创建此用户。

    #!/bin/bash
    
    if ! grep "^$1>" /etc/passwd &> /dev/null ; then
        useradd $1
        # 设定用户$1的密码是111
        echo "111" | passwd --stdin $1 &> /dev/null
        echo "add user $1 donw!"
    fi
    

    练习:比较2个数字的大小

    #!/bin/bash
    
    #声明一个变量,是整数。
    declare -i max
    #参数个数小于2
    if [ $# -lt 2 ]; then
        echo "at least one argu"
        exit 1
    fi
    #参数1大于参数2
    if [ $1 -ge $2 ]; then
        max=$1
    else
        max=$2
    fi
    echo "max number is $max"
    

    练习:判断给定用户名的id号是奇数还是偶数

    #!/bin/bash
    
    if [ $# -lt 1 ]; then
        echo "at least one argu"
        exit 1
    fi
    
    #取得用户的id
    uid=$(grep "^$1>" /etc/passwd | cut -d: -f3)
    echo $uid
    
    #判断奇偶数
    if [ $[$uid % 2] -eq 0 ]; then
        echo "oushu"
    else
        echo "jishu"
    fi
    

    运行结果:

    # bash jigou.sh ys
    1000
    oushu
    # bash jigou.sh fedora
    1005
    jishu
    

    练习:给2个文本文件路径,如果文件不存在,则结束脚本;都存在则返回每个文件的行数,并找出行数多的文件

    #!/bin/bash
    
    if [ $# -lt 2 ]; then
        echo "at least two argu"
        exit 1
    fi
    
    if ! [ -e $1 -a -e $2 ]; then
        exit 1
    else
        la=`wc -l < $1`
        lb=`wc -l < $2`
    
        echo "$1 行数:$la;$2 行数:$lb"
        if [ $la -ge $lb ]; then
            echo "$1 行数多"
        else
            echo "$2 行数多"
        fi
    
    fi
    

    运行结果:

    # bash sum1.sh /etc/passwd /etc/fstab
    /etc/passwd 行数:56;/etc/fstab 行数:13
    /etc/passwd 行数多
    
    

    case语法

    case $var in
        pat1)
    
            ;;
        pat2)
    
            ;;
        pat3)
    
            ;;
        *)
    
            ;;
    esac
    

    pat支持globbing风格:

    • *:匹配任意长度的任意字符
    • ?:匹配任意单个字符
    • []:匹配指定范围内的任意单个字符
    • [^]:匹配指定范围外的任意单个字符
    • {}:表示符合括号内包含的多个文件
    • aaa|bbb:aaa或bbb

    执行完脚本文件后,返回值是啥?

    默认是脚本文件里最后一条命令的返回值。

    可以自定义返回值:使用exit n命令,n为数字。

    当shell进程遇到exit命令时,进程会立即终止,因此exit后面的命令就不执行了。

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    你知道怎么离线安装全局 node 模块吗?
    关于开发视图
    你知道 JavaScript 中的 Arguments 对象都有哪些用途吗?
    前端 JavaScript 实现一个简易计算器
    Docker 系列 _ 01_ 一念缘起
    机器学习资料大全
    pdf、txt文本复制到EXCEL后的格式快速调整法
    习惯的养成
    磁盘剩余空间监控
    please wait while windows configures microsoft visual studio professional 2013
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/12084891.html
Copyright © 2011-2022 走看看