• 第三章 变量值操作和运算符


    一、变量值的操作

    1)获取变量值长度

    [root@jh /]# x="hello"
    [root@jh /]# echo ${#x}
    5
    
    # 企业面试题:已知变量msg='hello world!',请统计出变量中包含的字符数量
    # 方法一:
    [root@jh /]# echo ${#msg}
    12
    # 方法二:
    [root@jh /]# echo $msg | wc -L
    12
    # 方法三:
    [root@jh /]# echo $msg|awk '{print length}'
    12
    # 方法四:
    [root@jh ~]# expr length "$msg" #length是一个函数,注意因为msg的值有空格,所以$msg必
    须用引号包含
    12
    

    2)切片

    语法:${paramter:offset:length}
    
    #示例
    [root@jh /]# msg="abcdef"
    [root@jh /]# echo ${msg:3} # 从3号索引开始,一直到最后
    def
    [root@jh /]# echo ${msg:3:2} # 从3号索引开始,往后数2个字符
    de
    [root@jh /]# echo ${msg::3} # 从0开始,往后数3个字符
    abc
    

    3)截断

    # =================》一、砍掉左边的字符《=================
    # 1.1 简单使用
    [root@jh ~]# url="www.sina.com.cn"
    [root@jh ~]# echo ${url#www.}
    sina.com.cn
    # 1.2 结合*=》非贪婪,默认情况下*是非贪婪,尽可能地少“吃”字符
    [root@jh ~]# echo ${url#*w}
    ww.sina.com.cn
    # 1.3 结合*=》贪婪,尽可能地多“吃”字符
    [root@jh ~]# echo ${url##*w} # *会尽可能多地吃掉字符,一直匹配到最远的那个w才停下来
    .sina.com.cn
    # =================》二、砍掉右边的字符《=================
    # 1.1 简单使用
    [root@jh ~]# url="www.sina.com.cn"
    [root@jh ~]# echo ${url%.cn}
    www.sina.com
    # 1.2 结合*=》非贪婪
    [root@jh ~]# echo ${url%.*}
    www.sina.com
    # 1.3 结合*=》贪婪
    [root@jh ~]# echo ${url%%.*}
    www
    # =================》三、应用示例《=================
    [root@jh ~]# hostname
    jh.xxx.com
    [root@jh ~]# echo $HOSTNAME
    jh.xxx.com
    [root@jh ~]# echo ${HOSTNAME%.*}
    jh.xxx
    [root@jh ~]# echo ${HOSTNAME%%.*}
    jh
    

    4)内容的替换

    [root@jh ~]# url="www.sina.com.cn"
    [root@jh ~]# echo ${url/sina/baidu}
    www.baidu.com.cn
    [root@jh ~]# echo ${url/n/N}
    www.siNa.com.cn
    [root@jh ~]# echo ${url//n/N} # 贪婪
    www.siNa.com.cN
    
    # 应用示例:批量修改文件名称
    [root@jh shell]# touch jh_2020_{01..05}_linux.txt
    [root@jh shell]# ls
    jh_2020_01_linux.txt  jh_2020_02_linux.txt  jh_2020_03_linux.txt
     jh_2020_04_linux.txt  jh_2020_05_linux.txt
    [root@jh shell]# for i in `ls *linux.txt`;do mv $i ${i/_linux/};done
    [root@jh shell]# ls
    jh_2020_01.txt  jh_2020_02.txt  jh_2020_03.txt  jh_2020_04.txt
     jh_2020_05.txt
    

    5)变量的替代

    语法:
    ${x:-临时变量信息}
    ${x:=新的变量信息}
    ${x:?没有设置变量提示信息} 
    ${x:+有设置变量提示信息}
    
    #示例
    #1、${parameter-word}: 当调取变量没有定义过, 就返回word字符串信息
    [root@jh ~]# unset name
    [root@jh ~]# echo ${name}
    [root@jh ~]# echo ${name-"jh"} # 没有定义过变量name,则使用-后的值
    jh
    [root@jh ~]#
    [root@jh ~]# gender= # 定义过变量了,则使用变量的原值,哪怕变量的值为空值
    [root@jh ~]# echo ${gender-"male"}
    [root@jh ~]#
    [root@jh ~]# age=18 
    [root@jh ~]# echo ${age-19} # 定义过变量了,则使用变量的原值
    18
    [root@jh ~]#
    
    #2、${parameter:-word}: 当调取变量信息值为空时或未定义变量, 就返回word字符串信息
    [root@jh ~]# unset x 
    [root@jh ~]# unset y
    [root@jh ~]# unset z
    [root@jh ~]#
    [root@jh ~]# echo ${x:-aaa} # 没有定义过变量x,则使用-后的值
    aaa
    [root@jh ~]# y=
    [root@jh ~]# echo ${y:-aaa} # 定义过变量y,但变量y的值为空值,则使用-后的值
    aaa
    [root@jh ~]# z=333
    [root@jh ~]# echo ${z:-aaa} # 定义过变量了,并且变量有一个非空的原值,则使用变量的原值
    333
    
    #3、{parameter:=word}:当调取变量信息值为空时或未定义,则设置指定字符串为新的变量值
    [root@jh /]# unset x
    [root@jh /]# echo ${x:=123}
    123
    [root@jh /]# echo $x
    123
    
    #4、${parameter:?word}:当调取变量信息值为空时或未定义,指定为赋值的错误提示信息
    [root@jh /]# unset x
    [root@jh /]# echo ${x:?该变量没有定义过}
    -bash: x: 该变量没有定义过
       
    #5、${parameter:+word}:当调取变量信息值为空时或未定义,不做任何处理,否则word字符串将替代变量
    值
    [root@jh /]# unset x
    [root@jh /]# echo ${x:+哈哈哈}
    [root@jh /]# x=123
    [root@jh /]# echo ${x:+哈哈哈}
    哈哈哈
    

    6)let

    # (1) 变量的值
    [root@jh ~]# j=1
    [root@jh ~]# let ++j
    [root@jh ~]# echo $j
    2
    
    # (2) 表达式的值
    [root@jh ~]# unset i
    [root@jh ~]# unset j
    [root@jh ~]# i=1
    [root@jh ~]# j=1
    [root@jh ~]# let x=i++ # 先把i赋值给x,然后再++
    [root@jh ~]# let y=++j # 先++j,然后再把j的结果赋值给y
    [root@jh ~]# echo $i
    2
    [root@jh ~]# echo $j
    3
    [root@jh ~]# echo $x
    1
    [root@jh ~]# echo $y
    2
    

    二、单引号与双引号

    " " 弱引用,引号的特殊字符有意义
    ' ' 强引用,引号内所有特殊字符都取消意义
    [root@localhost ~]# school=“oldboy”
    [root@localhost ~]# echo "${school} is good"
    oldboy is good
    [root@localhost ~]# echo '${school} is good'
    ${school} is good
    

    三、将命令的结果赋值给变量

    # ``与$()
    ` `  命令替换 等价于 $()  反引号中的shell命令会被先执行
    [root@localhost ~]# touch `date +%F`_file1.txt 
    [root@localhost ~]# touch $(date +%F)_file2.txt
    [root@localhost ~]# disk_free3="df -Ph |grep '/$' |awk '{print $4}'" # 错误
    [root@localhost ~]# disk_free4=$(df -Ph |grep '/$' |awk '{print $4}') # 正确
    [root@localhost ~]# disk_free5=`df -Ph |grep '/$' |awk '{print $4}'` # 正确
    

    四、运算符

    1)算数运算符

    #算数运算符
    + - * / %
    
    算数运算符需要配合下述操作使用
    # 浮点运算
    bc 
    # 整数运算
    expr
    $(())
    $[]
    let
    
    详解如下
    #1、bc是比较常用的linux计算工具了,而且支持浮点运算
    [root@localhost ~]# res=`echo 1+1 | bc`
    [root@localhost ~]# echo $res
    2
    [root@localhost ~]# res=`echo 10 % 3 | bc`
    [root@localhost ~]# echo $res
    1
    [root@localhost ~]# res=`echo 1.2+1.3 | bc`
    [root@localhost ~]# echo $res
    2.5
    
    [root@localhost ~]# res=`echo 5.0+3.0 | bc`
    [root@localhost ~]# echo $res
    8.0
    [root@localhost ~]# res=`echo "scale=2;5.0/3.0" | bc`
    [root@localhost ~]# echo $res
    1.66
    [root@localhost ~]# res=`echo "scale=2;5.0/6.0" | bc`
    [root@localhost ~]# echo $res
    .83
    
    #2、expr不支持浮点数计算。而且要注意数字与运算符中的空格
    [root@localhost ~]# res=`expr 5 / 3` # 不支持浮点计算
    [root@localhost ~]# echo $res
    1
    [root@localhost ~]# res=`expr 1+1` # 注意:要有空格
    [root@localhost ~]# echo $res
    1+1
    [root@localhost ~]# res=`expr 1 + 1`
    [root@localhost ~]# echo $res
    2
    
    #3、$(()) 同expr,不支持浮点数运算
    # 例如:
    [root@localhost ~]# echo $((1+1))
    2
    [root@localhost ~]# echo $((1.0+2.0)) # 不支持浮点运算符
    -bash: 1.0+2.0: 语法错误: 无效的算术运算符 (错误符号是 ".0+2.0")
        
    # 注意:
    echo $(($num1+$num2))  # 也可以简写为 echo $((num1+num2))
    echo $(((5-3)*2))  # 可以嵌套括号  
    
    #4、$[]同expr以及$(()),不支持浮点运算
    [root@jh ~]# echo $[$num1+$num2] # 等同于 echo $[num1+num2]
    333
    [root@jh ~]# echo $[1.3+3.1]
    -bash: 1.3+3.1: 语法错误: 无效的算术运算符 (错误符号是 ".3+3.1")
    
    #5、let 不支持浮点数运算,而且不支持直接输出,只能赋值
    [root@localhost ~]# let res=1+1
    [root@localhost ~]# echo $res
    2
    [root@localhost ~]#
    [root@localhost ~]# let res=50/5
    [root@localhost ~]# echo $res
    10
    [root@localhost ~]# let c=1.3*3
    -bash: let: c=1.3*3: 语法错误: 无效的算术运算符 (错误符号是 ".3*3"
    
    #6、强调:整数与非整数之间运算会报错
    [root@jh ~]# expr 1 + a
    expr: 非整数参数
    [root@jh ~]# expr 1 + 1.3
    expr: 非整数参数
    

    2)测试运算符

    测试命令:test,详细可用man test查询
    测试符号:[],注意只有一层中括号,中括号内左右两侧必须要有空格
    test与[]效果都一样,参数也都一样
    

    1.测试文件状态

    1. -d 目录
    [root@jh ~]# test -d /etc/ ; echo $?
    0
    [root@jh ~]# [ -d /etc ];echo $? # 注意[]内左右两侧要有空格
    0
    ps:下面关于[]用法都与test一样,不再举例
    
    
    2.-s 文件长度 > 0、非空
    [root@jh ~]# touch a.txt
    [root@jh ~]# test -s a.txt ;echo $? # 文件为空则返回假
    1
    [root@jh ~]# test -s /etc/passwd ;echo $? # 文件不为空则返回假
    0
    
    3.-f 正规文件
    [root@jh ~]# test -f /etc/passwd;echo $?
    0
    
    4.-w 可写
    [jh@jh ~]$ touch a.txt
    [jh@jh ~]$ chmod a-w a.txt
    [jh@jh ~]$ [ -w a.txt ];echo $?  # 返回假,注意,如果是root用户,无论如何都有
    写权限
    1
    
    5.-r 可读
    [jh@jh ~]$ ll a.txt
    -r--r--r--. 1 jh jh 292 8月  17 21:48 a.txt
    [jh@jh ~]$ test -r a.txt;echo $?
    0
    
    6.-x 可执行
    [jh@jh ~]$ ll a.txt
    -r--r--r--. 1 jh jh 292 8月  17 21:48 a.txt
    [jh@jh ~]$ test -x a.txt;echo $?
    1
    
    7.-L 符号连接
    [root@jh ~]# ll -d /lib64
    lrwxrwxrwx. 1 root root 9 7月  14 03:33 /lib64 -> usr/lib64
    [root@jh ~]# test -L /lib64;echo $?
    0
    
    8.-u 文件有 suid 位设置
    [root@jh ~]# ll /usr/bin/passwd
    -rwsr-xr-x. 1 root root 27832 6月  10 2014 /usr/bin/passwd
    [root@jh ~]# [ -u `which passwd` ];echo $?
    0
    [root@jh ~]# [ -u `which ls` ];echo $?
    1
    

    2.字符串测试

    1.== 两个字符串相等
    [root@jh ~]# [ "aaa" == "aaa" ];echo $?
    0
    
    2.!= 两个字符串不相等
    [root@jh ~]# [ "aaa" != "aaa" ];echo $?
    1
    
    3.-z 字符串长度为零
    [root@jh ~]# ip=""
    [root@jh ~]# [ -z "$ip" ];echo $? # 注意引号
    0
    [root@jh ~]# ip='1.1.1.1'
    [root@jh ~]# [ -z "$ip" ];echo $?
    1
    
    4.-n 字符串长度不为零
    [root@jh ~]# [ -n "$ip" ];echo $? # 注意加引号
    1
    

    3.测试数值

    #test与[]也可以测试数值,与 [[]]和(())效果一样
    -eq 等于
    -ne 不等于
    -gt 大于
    -lt 小于
    -ge 大于等于
    -le 小于等于
    -a并且
    -o或者
    
    [root@jh ~]# [ 10 -eq 10 ];echo $?
    0
    [root@jh ~]# [ 10 -eq 10 -a 10 > 3 ];echo $?
    0
    # 1、示例:
    [root@jh ~]# disk_use=$(df -P |grep '/$' |awk '{print $5}' |awk -F%
    '{print $1}')
    [root@jh ~]# [ $disk_use -gt 10 ] && echo "warn......"
    warn......
    [root@jh ~]# [ $(id -u) -eq 0 ] && echo "当前是超级用户" || echo "you不是超级
    用户"
    当前是超级用户
    

    3)关系运算符

    #关系运算符号:
    < > <= >= == != && ||
    上述关系运算符需要配合(())使用(注意(())属于C语言风格的比较),最终都是用来当if判断或者while循环的条件
    
    [root@jh ~]# x=100
    [root@jh ~]# (($x>10))
    [root@jh ~]# echo $?
    0
    [root@jh ~]# (($x < 10));echo $?
    1
    [root@jh ~]# (($x == 100));echo $?
    0
    [root@jh ~]# (($x != 100));echo $?
    1
    [root@jh ~]# (($x != 100)) && (("jh" == "jh"))
    [root@jh ~]# echo $?
    1
    [root@jh ~]# (($x != 100)) || (("jh" == "jh"))
    [root@jh ~]# echo $?
    0
    [root@jh ~]# (($x != 100 && "jh" == "jh"));echo $?
    1
    [root@jh ~]# (($x != 100 || "jh" == "jh"));echo $?
    0
    

    4)赋值运算符

    #赋值运算符号
    = += *= /= %=
    
    #示例:
    1.=
    [root@jh ~]# x=10
    [root@jh ~]# echo $x
    10
    
    2.+=
    [root@db04 ~]# age=18
    [root@db04 ~]# ((age+=10))
    [root@db04 ~]# echo $age
    28
    
    3.*=
    [root@db04 ~]# age=18
    [root@db04 ~]# ((age*=10))
    [root@db04 ~]# echo $age
    180
    
    4./= 除数取整
    [root@db04 ~]# age=18
    [root@db04 ~]# ((age/=10))
    [root@db04 ~]# echo $age
    1
    
    5.%=  取余
    [root@db04 ~]# age=18
    [root@db04 ~]# ((age%=9))
    [root@db04 ~]# echo $age
    0
    

    5)其他的元字符

    [[]]与[]基本一样,不同的是[[]]支持正则匹配,不过要注意的是必须在内层中括号内左右两侧加空格
    
    [root@jh ~]# [[ "$USER" == "root" ]];echo $? # 注意内层[]中包含的内容必须左右两侧
    加空格
    0
    [root@jh ~]# [[ "$USER" == "root" ]];echo $? # 一个等号也行两个等号也可以额
    0
    
    # 此外[[]]内部是可以使用正则的,注意:正则表达式不要加引号
    [root@jh ~]# [[ "$USER" =~ "^root$" ]];echo $? # 正则表达式不要加引号
    1
    [root@jh ~]# [[ "$USER" =~ ^root$ ]];echo $? # 正则表达式不要加引号
    0
    [root@jh ~]# [[ ! "$USER" =~ t$ ]] && echo 此时不是管理员登录 || echo 是管理员登录
    是管理员登录
    
    [root@jh ~]# num1=123
    [root@jh ~]# [[ "$num1" =~ ^[0-9]+$ ]];echo $? # 判断是否是数字
    0
    [root@jh ~]# [[ "$num1" =~ ^[0-9]+$ ]] && echo "是数字"
    是数字
    [root@jh ~]# num2=abc123de
    [root@jh ~]# [[ "$num2" =~ ^[0-9]+$ ]];echo $?
    1
    [root@jh ~]# [[ "$num2" =~ ^[0-9]+$ ]] || echo "num2不是数字"
    num2不是数字
    

    6)补充浮点数的比较

    # 需要注意的是:bc的结果为1代表真,为0代表假
    [root@jh ~]# echo "10.3 >= 10.1" | bc
    1
    [root@jh ~]# echo "10.3 != 10.1" | bc
    1
    [root@jh ~]# echo "10.3 != 10.3" | bc
    0
    # 应用
    [root@jh ~]# x=10.3
    [root@jh ~]# y=10.1
    [root@jh ~]# [ `echo "$x >= $y" | bc` -eq 1 ] && echo "$x 大于 $y"
    10.3 大于 10.1
    

    五、总结

    1.条件测试:
    格式1: test 条件表达式
    格式2: [ 条件表达式 ]
    格式3: (()) 数值比较,运算  C语言
    格式4: [[ 条件表达式 ]],支持正则 =~
    
    2.结合$符号
    $[]  # 整数运算
    $(())  # 整数运算
    $()   # 命令替换
    
    3.其他
    ()   # 子shell中执行
    

    六、练习题

    1)算数运算符练习题

    #1、脚本案例: 编写小脚本, 可以实现2位数加减乘除运算
    [root@jh shell]# cat a.sh
    #!/bin/bash
    a=$1
    b=$2
    [ $# -ne 2 ] && {
      echo "请输入两位数字信息"
      exit
    }
    echo "a-b=$((a-b))"
    echo "a+b=$((a+b))"
    echo "a*b=$((a*b))"
    echo "a/b=$((a/b))"
    
    # 2、脚本案例: 编写判断输入参数是否是整数信息脚本
    #!/bin/bash
    #Auther jh 2020-11-18 version 1 des:/scripts/day03/math03.s
    h
    
    read -p "请输入一个数:" input_num
    expr $input_num + 0 &>/dev/null && echo $? &>/dev/null  # 只有整型加0才不会报错,浮点数及字符与0详解都会报错
    if [ $? -eq 0 ];then
        echo "此数为整数"
    else
        echo "此数为非整数"
    fi
    
    # 3、如何利用脚本计算1+2+3+4..10总和数值
    方法一:
    seq -s "+" 10|bc
    方法二:
    echo {1..10}|tr " " "+"|bc
    方法三:
    awk 'BEGIN{for (i=1; i<=10; i++) a=a+i; print a}'
    方法四:
    declare -i i=1
    declare -i sum=0
    while ((i<=10))
    do
      let sum+=i
      let ++i
    done
    echo $sum
    
    方法五:
    for i in {1..10}
    do
      let a=$a+$i
    done
      echo $a
    
    

    2)企业面试题

    企业面试题1: 传入两个数值信息, 自动让脚本显示数值比较情况
    root@jh shell]# cat num.sh
    #!/bin/bash
    [ $# -ne 2 ] && echo "只能传入两个整数" && exit
    [[ ! $1 =~ ^[0-9]+$ ]] && echo "参数1必须是整数" && exit
    [[ ! $2 =~ ^[0-9]+$ ]] && echo "参数2必须是整数" && exit
    [[ $1 -lt $2 ]] && echo "$1 < $2"
    [[ $1 -gt $2 ]] && echo "$1 > $2"
    [[ $1 -eq $2 ]] && echo "$1 = $2"
    [root@jh shell]# chmod +x num.sh
    [root@jh shell]# ./num.sh 17 37
    17 < 37
    

  • 相关阅读:
    VMWARE虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本。 模块“Upgrade”启动失败。 未能启动虚拟机。
    常见Dos命令
    Javatest
    Java多线程
    idea/eclipse 常用快捷键
    单例模式
    x865中断和异常
    x866特权级
    x867页式管理(Paging)
    x864任务(task)
  • 原文地址:https://www.cnblogs.com/jhno1/p/14026312.html
Copyright © 2020-2023  润新知