shell之变量

1、概述

  • shell变量名的命名须遵循如下规则:

    • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
    • 中间不能有空格,可以使用下划线(_)。
    • 不能使用标点符号。
    • 不能使用bash里的关键字(可用help命令查看保留关键字)。
  • 有效的shell变量名示例如下:

    1
    2
    3
    4
    RUNOOB
    LD_LIBRARY_PATH
    _var
    var2
  • 无效的变量命名如下:

    1
    2
    ?var=123
    user*name=runoob

2、变量定义

  • ①自定义变量。

    • 定义变量:变量名=变量值 ,变量名必须以字母或者下划线开头,区分大小写。

    • 引用变量:$变量名或者${变量名}

    • 查看变量:echo $变量名。

    • 取消变量:unset 变量名。

      • eg:1:判断通过变量定义的主机是否能ping通。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        #!/usr/bin/bash
        ip=www.baidu.com

        ping -c1 $ip &>/dev/null
        if [ $? -eq 0 ]; then
        echo "$ip is up."
        else
        echo "$ip is down."
        fi
      • eg2:判断通过键盘读入定义的主机是否能ping通。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        #!/usr/bin/bash
        read -p "Please input a ip:" ip

        ping -c1 $ip &>/dev/null
        if [ $? -eq 0 ]; then
        echo "$ip is up."
        else
        echo "$ip is down."
        fi
      • eg2:判断通过位置变量定义的主机是否能ping通。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        #!/usr/bin/bash
        # $1 位置变量
        ping -c1 $1 &>/dev/null
        if [ $? -eq 0 ]; then
        echo "$1 is up."
        else
        echo "$1 is down."
        fi

        # 运行命令:bash ./test.sh www.baidu.com
  • ②环境变量。

    • 定义变量:export 变量名=变量值export 变量名将自定义变量转换成环境变量。

    • 引用环境变量:$变量名或者${变量名}

    • 查看环境变量:echo $变量名env

    • 取消环境变量:unset 变量名。

      • eg1:测试变量作用范围。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        [root@centos7 shell]# ip1=1.1.1.1
        [root@centos7 shell]# export ip2=2.2.2.2
        [root@centos7 shell]# vim test.sh
        [root@centos7 shell]# cat test.sh
        echo "ip1 is: $ip1"
        echo "ip2 is: $ip2"
        [root@centos7 shell]# bash ./test.sh # 在子shell中执行
        ip1 is:
        ip2 is: 2.2.2.2
        [root@centos7 shell]# . test.sh # 在当前shell中执行
        ip1 is: 1.1.1.1
        ip2 is: 2.2.2.2
      • eg2:不定义环境变量(父子shell都能使用的变量),因为可以在当前脚本中使用另外一个脚本,使得变量共享。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        [root@centos7 shell]# vim public.sh
        [root@centos7 shell]# cat public.sh
        ip3=3.3.3.3
        dir_path=/etc
        [root@centos7 shell]# vim test2.sh
        [root@centos7 shell]# cat test2.sh
        . public.sh #这里可以是相对路径,也可以是绝对路径,.表示在当前shell执行
        echo "ip3 is: $ip3"
        echo "dir_path is: $dir_path"
        [root@centos7 shell]# bash test2.sh
        ip3 is: 3.3.3.3
        dir_path is: /etc
  • ③预定义变量。

    符号 说明
    $0 脚本名
    $*、$@ 所有的参数
    $# 参数的个数
    $$ 当前进程的PID
    $! 上一个后台进程的PID
    $? 上一个命令的返回值,0表示成功
    • eg1:测试指定文件中的ip地址是否能ping通。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      [root@centos7 shell]# cat test3.sh
      #!/usr/bin/bash
      #提示方法,如果用户没有加参数
      if [ $# -eq 0 ];then
      echo "uasge: `basename $0` file" #basename只显示最后一个名字,eg:basename /home/wangji/cc,只显示cc
      exit
      fi

      ##判断是否为文件
      if [ ! -f $1 ];then
      echo "error file!"
      exit
      fi

      for ip in `cat $1`
      do
      ping -c1 -W1 $ip &>/dev/null
      if [ $? -eq 0 ];then
      echo "$ip is up"
      else
      echo "$ip is down"
      fi
      done
      [root@centos7 shell]# cat test.txt
      1.1.1.1
      2.2.2.2
      3.3.3.3
      [root@centos7 shell]# ./test3.sh test.txt
      1.1.1.1 is up
      2.2.2.2 is down
      3.3.3.3 is down
  • 变量匹配。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    [root@centos7 shell]# url=www.sina.com.cn
    [root@centos7 shell]# echo ${#url} # 获取变量值的长度
    15
    [root@centos7 shell]# echo ${url} # 标准查看
    www.sina.com.cn
    [root@centos7 shell]# echo ${url#*.} # 从前往后,最短匹配
    sina.com.cn
    [root@centos7 shell]# echo ${url##*.} # 从前往后,最长匹配,贪婪匹配
    cn
    [root@centos7 shell]# echo ${url%.*} # 从后往前,最短匹配
    www.sina.com
    [root@centos7 shell]# echo ${url%%.*} # 从后往前,最长匹配,贪婪匹配
    www
    [root@centos7 shell]# echo ${url#a.} # 错误的结果
    www.sina.com.cn
    [root@centos7 shell]# echo ${url#*sina.} # 正确的结果
    com.cn

3、变量赋值

  • ①显示赋值:变量名=变量值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # ` `是命令替换,换等价于$(),其中的shell命令会被先执行
    [root@centos7 shell]# today=`date +%F`
    [root@centos7 shell]# echo today
    today
    [root@centos7 shell]# today=`date +%F`
    [root@centos7 shell]# echo $today
    2021-08-09
    [root@centos7 shell]# today2=$(date +%F)
    [root@centos7 shell]# echo $today2
    2021-08-09
  • ②read从键盘读入变量值。

    1
    2
    3
    4
    read 变量名
    read -p "提示信息:" 变量名 # -p:"提示信息",在等待read输入时,输出提示信息
    read -t 5 -p "提示信息:" 变量名 # -t:秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间
    read -n 2 变量名 # -n:字符数:read命令只接收指定的字符数就会执行
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [root@centos7 shell]# read ip
    1.1.1.1
    [root@centos7 shell]# echo $ip
    1.1.1.1
    [root@centos7 shell]# read -p "Please input: " ip
    Please input: 2.2.2.2
    [root@centos7 shell]# echo $ip
    2.2.2.2
    [root@centos7 shell]# read -n 2 name
    ab[root@centos7 shell]# echo $name
    ab
    • 定义或引用变量时的注意事项:

      1
      2
      3
      4
      5
      [root@centos7 shell]# school=longhu
      [root@centos7 shell]# echo "$school is good" # " "弱引用
      longhu is good
      [root@centos7 shell]# echo '$school is good' # ' '强引用
      $school is good

4、变量运算

  • ①整数运算。

    • 方法一:expr。

      1
      2
      3
      4
      5
      6
      7
      8
      [root@centos7 shell]# num1=10
      [root@centos7 shell]# num2=20
      [root@centos7 shell]# sum=`expr $num1 + $num2`
      [root@centos7 shell]# echo $sum
      30
      [root@centos7 shell]# sum=`expr $num1 \* $num2`
      [root@centos7 shell]# echo $sum
      200
    • 方法二:$(())。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      [root@centos7 shell]# num1=1
      [root@centos7 shell]# num2=2
      [root@centos7 shell]# sum=$((1+2));echo $sum
      3
      [root@centos7 shell]# echo $((5-3*2))
      -1
      [root@centos7 shell]# echo $(($num1+$num2))
      3
      [root@centos7 shell]# echo $((2**3))
      • eg:测试当前系统内存使用百分比。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        [root@centos7 shell]# cat memuse.sh
        #!/usr/bin/bash
        mem_used=`free -m |grep '^Mem:' |awk '{print $3}'`
        mem_total=`free -m |grep '^Mem:'|awk '{print $2}'`
        mem_percent=$((mem_used*100/mem_total))

        echo "当前内存使用的百分比:$mem_percent"
        [root@centos7 shell]# bash -vx memuse.sh # 使用调试方式去执行脚本
        #!/usr/bin/bash
        mem_used=`free -m |grep '^Mem:' |awk '{print $3}'`
        free -m |grep '^Mem:' |awk '{print $3}'
        ++ grep '^Mem:'
        ++ awk '{print $3}'
        ++ free -m
        + mem_used=812
        mem_total=`free -m |grep '^Mem:'|awk '{print $2}'`
        free -m |grep '^Mem:'|awk '{print $2}'
        ++ grep '^Mem:'
        ++ awk '{print $2}'
        ++ free -m
        + mem_total=1980
        mem_percent=$((mem_used*100/mem_total))
        + mem_percent=41

        echo "当前内存使用的百分比:$mem_percent"
        + echo 当前内存使用的百分比:41
        当前内存使用的百分比:41
    • 方法三:$[]。

      1
      2
      3
      4
      [root@centos7 shell]# echo $[5+2]
      7
      [root@centos7 shell]# echo $[5*2]
      10
    • 方法四:let。

      1
      2
      3
      4
      [root@centos7 shell]# let num=2+3;echo $sum
      3
      [root@centos7 shell]# let i++;echo $i
      1
  • ②小数运算。

    1
    2
    3
    4
    5
    6
    7
    # 在shell中做小数运算,可以借助bc或者awk工具
    [root@centos7 shell]# awk 'BEGIN{print 1/2}'
    0.5
    [root@centos7 shell]# echo "print 5.0/2" |python
    2.5
    [root@centos7 shell]# echo "scale=2;6/4" |bc # 保留小数点后2位
    1.50

5、索引与切片

  • eg:

    1
    2
    3
    4
    5
    6
    7
    [root@centos7 shell]# url=www.sina.com.cn
    [root@centos7 shell]# echo ${url:0:5} # 从第0个取,取5个
    www.s
    [root@centos7 shell]# echo ${url:5:5} # 从第5个取,取5个
    ina.c
    [root@centos7 shell]# echo ${url:5} # 从第5个开始取
    ina.com.c

6、变量替换

  • eg1:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [root@centos7 shell]# url=www.sina.com.cn
    [root@centos7 shell]# echo ${url}
    www.sina.com.cn
    [root@centos7 shell]# echo ${url/sina/baidu} # 将sina替换成baidu
    www.baidu.com.cn
    [root@centos7 shell]# echo ${url/n/N} # 将n替换成N
    www.siNa.com.cn
    [root@centos7 shell]# echo ${url//n/N} # 将所有n替换成N,//表示贪婪匹配
    www.siNa.com.cN
  • eg2:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # ${变量名-新的变量值}
    # 变量没有被赋值:会使用"新的变量值"替换
    # 变量有被赋值(包括空值):不会被替代
    [root@centos7 shell]# unset var1
    [root@centos7 shell]# echo ${var1}

    [root@centos7 shell]# echo ${var1-aaa}
    aaa
    [root@centos7 shell]# var2=111
    [root@centos7 shell]# echo ${var2-bbb}
    111
    [root@centos7 shell]# var3=
    [root@centos7 shell]# echo ${var3-ccc}

  • eg3:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # ${变量名:-新的变量值}
    # 变量没有被赋值(包括空值):都会使用“新的变量值”替代
    # 变量有被赋值:不会被替代
    [root@centos7 shell]# unset var1
    [root@centos7 shell]# unset var2
    [root@centos7 shell]# unset var3
    [root@centos7 shell]# var2=
    [root@centos7 shell]# var3=111
    [root@centos7 shell]# echo ${var1:-aaaa}
    aaaa
    [root@centos7 shell]# echo ${var2:-aaaa}
    aaaa
    [root@centos7 shell]# echo ${var3:-aaaa}
    111
  • eg4:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 其它例子
    echo ${var3+aaa}:假如var3设为空值或非空值,均使用aaa作传回值。(没设定时不作处理)
    echo ${var3:+aaa}:若var3为非空值,则使用aaa作传回值。(没设定及空值时不作处理)

    echo ${var3=aaa}:若var3没设定,则使用aaa作传回值,同时将var3赋值为aaa。(空值及非空值时不作处理)
    echo ${var3:=aaa}:若var3没设定或为空值,则使用aaa作传回值,同时将var3赋值为aaa。(非空值时不作处理)

    echo ${var3?aaa}:若var3没设定,则将aaa输出出至STDERR。(空值及非空值时不作处理)
    echo ${var3:?aaa}:若var3没设定或为空值,则将aaa输出至STDERR。(非空值时不作处理)