zoukankan      html  css  js  c++  java
  • shell(shell变量、条件表达式、流程控制)

    本章内容:

    1. 变量
    2. 运算
    3. if语句
    4. for语句
    5. while语句
    6. break、continue
    7. 实例

    shell变量

    1、shell变量简介

    变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据。脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则。

    在 Bash shell 中,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储;这意味着,Bash shell 在默认情况下不会区分变量类型,即使你将整数和小数赋值给变量,它们也会被视为字符串,这一点和大部分的编程语言不同。

    2、定义变量

    Shell 常用三种定义变量的方式:

    variable=value
    variable='value'    #所见即所得
    variable="value"   #进行转义
    variable=`cat test`  #执行命令将命令输出赋值给变量  
    

    Shell 变量的命名规范和大部分编程语言都一样:

    • 变量名由数字、字母、下划线组成;
    • 必须以字母或者下划线开头;
    • 不能使用 Shell 里的关键字(通过 help 命令可以查看保留关键字)。

    3、使用变量

    ╭─root@localhost.localdomain ~  
    ╰─➤  aa="cjk"
    ╭─root@localhost.localdomain ~  
    ╰─➤  echo $aa
    cjk
    ╭─root@localhost.localdomain ~  
    ╰─➤  echo ${aa}   #推荐给所有变量加上花括号{ },这是个良好的编程习惯
    cjk
    

    4、删除变量

    使用 unset 命令可以删除变量

    ╭─root@localhost.localdomain ~  
    ╰─➤  aa="cjk"
    ╭─root@localhost.localdomain ~  
    ╰─➤  echo ${aa}
    cjk
    ╭─root@localhost.localdomain ~  
    ╰─➤  unset aa   #unset 命令不能删除只读变量
    ╭─root@localhost.localdomain ~  
    ╰─➤  echo ${aa}
    

    5、变量类型

    运行shell时,会同时存在三种变量:

    局部变量

    局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。

    环境变量

    所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。

    shell变量

    shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    6、系统变量

    在命令行提示符直接执行 env、set 查看系统或环境变量。env 显示用户环境变量,set 显示 Shell 预先定义好的变量以及用户变量。可以通过 export 导出成用户变量。一些写 Shell 脚本时常用的系统变量

    系统变量名 系统变量意识
    $SHELL 默认 Shell
    $HOME 当前用户家目录
    $IFS 内部字段分隔符
    $LANG 默认语言
    $PATH 默认可执行程序路径
    $PWD 当前目录
    $UID 当前用户 ID
    $USER 当前用户
    $HISTSIZE 历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间
    $RANDOM 随机生成一个 0 至 32767 的整数
    $HOSTNAME 主机名

    生成8位随机数:echo "$RANDOM"|md5sum|cut -c 1-8

    7、普通变量和环境变量

    • 普通变量定义:VAR=value
    • 临时环境变量定义:export VAR=value
    • 变量引用:$VAR
    • 区别:Shell 进程的环境变量作用域是 Shell 进程,当 export 导入到系统变量时,则作用域是 Shell 进程及其 Shell 子进程,另开shell无效。

    8、特殊变量列表(shell变量)

    变量 含义
    $0 当前脚本的文件名
    $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
    $# 传递给脚本或函数的参数个数。
    $* 传递给脚本或函数的所有参数。
    $? 上个命令的退出状态,或函数的返回值,成功会返回 0,失败返回非0
    $$ 当前Shell进程ID,对于 Shell 脚本,就是这些脚本所在的进程ID

    实例:

    ╭─root@localhost.localdomain ~  
    ╰─➤  vim test.sh
    ...
    #!/bin/bash
    
    echo "File Name: $0"
    
    echo "First Parameter : $1"
    
    echo "First Parameter : $2"
    
    echo "Quoted Values: $@"
    
    echo "Quoted Values: $*"
    
    echo "Total Number of Parameters : $#"
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh  hello cjk touch
    File Name: test.sh
    First Parameter : hello
    First Parameter : cjk
    Quoted Values: hello cjk touch
    Quoted Values: hello cjk touch
    Total Number of Parameters : 3
    ╭─root@localhost.localdomain ~  
    ╰─➤  echo $?                      
    0
    ╭─root@localhost.localdomain ~  
    ╰─➤  ddd ddd
    zsh: command not found: ddd
    ╭─root@localhost.localdomain ~  
    ╰─➤  echo $?    
    127
    
    

    shift 命令 将参数向前移一位
    shift n 向前移n位


    shell条件表达式与运算符

    9、条件表达式

    表达式 实例
    [ expression ] [ 1 -eq 1 ]
    [[ expression ]] [[ 1 -eq 1 ]]
    test expression test 1 -eq 1 ,等同于[]

    注意:括号中的表达式前后都有空格,否则会报错!

    ╭─root@localhost.localdomain ~  
    ╰─➤  [ 1 -eq 1 ] && echo "true" || echo "false"
    true
    ╭─root@localhost.localdomain ~  
    ╰─➤  [ 1 -eq 2 ] && echo "true" || echo "false"
    false
    ╭─root@localhost.localdomain ~  
    ╰─➤  [1 -eq 2] && echo "true" || echo "false" 
    zsh: bad pattern: [1
    
    

    10、整数比较符

    比较符 描述 实例
    -eq, equal 等于 [ 1 -eq 1 ] 为true
    -ne, not equal 不等于 [ 1 -ne 1 ] 为false
    -gt, greate than 大于 [ 1 -gt 1 ] 为false
    -lt, lesser than 小于 [ 1 -lt 1 ] 为false
    -ge, greate or equal 大于或者等于 [ 1 -ge 1 ] 为true
    -le, lesser or equal 小于或者等于 [ 1 -le 1 ] 为true

    11、字符串比较符

    运算符 描述 实例
    == 等于 [ “a” == “a” ] 为true
    != 不等于 [ “a” != “a” ] 为false
    -n 字符串长度不等于 0 为真 VAR1=1;VAR2=””
    [ -n “$VAR1” ]为 true
    [ -n “$VAR2” ]为 false
    -z 字符串长度等于 0 为真 VAR1=1;VAR2=””
    [ -z “$VAR1” ]为false
    [ -z “$VAR2” ]为 true

    注意:使用-n 判断字符串长度时,变量要加双引号,养成好习惯,字符串比较时都加上双引号

    12、文件测试

    测试符 描述 实例
    -e 文件或者目录存在为真 [ -e path ] path 存在为 true
    -f 文件存在为真 [ -f file_path ] 文件存在为 true
    -d 目录存在为真 [ -d dir_path ] 目录存在为 true
    -r 有读权限为真 [ -r file_path ]file_path有读权限为真
    -w 有写权限为真 [ -w file_path ]file_path有写权限为真
    -x 有执行权限为真 [ -x file_path ]file_path有执行权限为真
    -s 文件存在且不为空为真 [-s file_path]file_path存在且不为空为真

    13、布尔运算符

    运算符 描述 实例
    非关系,条件结果取反 [ ! 1 -eq 2 ]为true
    -a 和关系,在[]表达式中使用 [ 1 -eq 1 -a 2 -eq 2 ]为true
    两者都为真才为真
    -o 或关系,在[]表达式中使用 [ 1 -eq 1 -o 2 -eq 1 ]为true
    两者有一真则为真

    14、逻辑判断符

    判断符 描述 实例
    && 逻辑和,在[[]]表达式中或判断表达式是否为真时使用 [[ 1 -eq 1 && 2 -eq 2 ]]为 true
    [ 1 -eq 1 ] && echo ‘true’
    如果&&前面的表达式为true则执行后面的
    || 逻辑或,在[[]]表达式中或判断表达式是否为真时使用 [[ 1 -eq 1 || 2 -eq 1 ]]为 true
    [ 1 -eq 2 ] || echo ‘true’
    如果||前面的表达式为false则执行后面的

    15、整数运算符

    运算符 描述
    + 加法
    减法
    * 乘法
    / 除法
    % 取余
    运算表达式 实例
    $(()) $((1+1))
    $[] $[]

    16、其他运算符

    命令 描述 实例
    let 赋值并运算 let x++;echo $x 每执行一次 x 加 1
    let y–;echo $y 每执行一次 y 减 1
    let x+=2 每执行一次 x 加 2
    let x-=2 每执行一次 x 减 2
    expr 乘法*需要转义"*" expr 1 * 2 运算符两边必须有空格
    expr( 1 + 2) * 2 使用双括号时要转义

    if语句

    if语句用exit结束

    1.1单分支

    if 条件表达式 ;then
    
        命令
    
    fi
    

    实例:

    #!/bin/bash
    read -p "请输入数字" num
    if [ $num -lt 10 ] ;then
            echo "${num}是数字两位数"
    fi
    ...
    
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh
    请输入数字3
    3是数字一位数
    
    

    1.2、多分支

    if 条件表达式 ;then
        命令
    else
        命令
    fi
    

    实例:

    #!/bin/bash
    read -p "请输入数字" num
    if [ $num -gt 9 -a $num -lt 100 ] ;then
            echo "${num}是数字两位数"
    else
            echo "${num}不是数字两位数"
    fi
    ...
    
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh 
    请输入数字56
    56是数字两位数
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh
    请输入数字222
    222不是数字两位数
    
    

    1.3、多分支

    if 条件表达式 ;then
        命令
    elif 条件表达式 ;then
        命令
    else
        命令
    fi
    

    实例:

    #!/bin/bash
    num=`echo $RANDOM`
    if [ $num -lt 1000 ];then
            echo "$num小于1000"
    elif [ $num -ge 1000 -a $num -lt 2000 ];then
            echo "$num大于等于1000,小于2000"
    elif [ $num -ge 2000 -a $num -lt 3000 ];then
            echo "$num大于等于2000,小于3000"
    elif [ $num -ge 3000 -a $num -lt 4000 ];then
            echo "$num大于等于3000,小于4000"
    else
            echo "$num大于等于4000"
    fi
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh
    24497大于等于4000
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh
    20763大于等于4000
    
    

    for 循环

    for  变量名  in  取值列表
    
    do
    
        命令
    
    done
    

    实例:

    #!/bin/bash
    . /etc/init.d/functions
    ip=192.168.80.
    for i in `seq 10`
    do
            if ping -c 1 -w 1 $ip$i &>/dev/null;then
                    echo -n " $ip$i"    #-n:作用不换行  ;$ip前有空格
                    success
                    echo " "
                    sleep 1
            else
                    echo -n " $ip$i"
                    failure
                    echo " "
                    sleep 1
            fi
    done
    
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh
     192.168.80.1                                              [  OK  ]
     192.168.80.2                                              [  OK  ]
     192.168.80.3                                              [  OK  ]
     192.168.80.4                                              [  OK  ]
     192.168.80.5                                              [FAILED]
     192.168.80.6                                              [FAILED]
     192.168.80.7                                              [FAILED]
     192.168.80.8                                              [FAILED]
     192.168.80.9                                              [FAILED]
     192.168.80.10                                             [FAILED]
    
    

    while循环

    while 条件表达式 ; do
    
          命令
    
    done
    

    3.1、一般循环

    当条件表达式为 false 时,终止循环

    实例:

    #!/bin/bash
    N=0
    while [ $N -lt 5 ]; do
            echo $N
            let N++
    done
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test1.sh
    0
    1
    2
    3
    4
    

    3.2、死循环

    条件表达式为 true,将会产生死循环

    #!/bin/bash
    while true ;do
            echo "hello"
            sleep 1
    done
    
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test2.sh
    hello
    hello
    hello
    hello
    hello
    ^C
    
    • 命令行中输入 nohup bash naolie.sh & 即可在后台持续运行该脚本

    break和continue语句

    • continue 与 break 语句只能循环语句中使用;
    • break:终止循环,运行针跳至done后;
    • continue :跳出当前循环,运行针跳至do后,开始下一循环;

    演示:
    break语句

    #!/bin/bash
    N=0
    while [ $N -lt 10 ]; do
            let N++
            if [ $N -eq 5 ]; then
                    break
            fi
            echo $N
    done
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test1.sh
    1
    2
    3
    4
    

    continue语句

    #!/bin/bash
    N=0
    while [ $N -lt 10 ]; do
            let N++
            if [ $N -eq 5 ]; then
                    continue
            fi
            echo $N
    done
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test1.sh
    1
    2
    3
    4
    6
    7
    8
    9
    10
    

    实例拓展:

    实例1:

    #!/bin/bash
    echo "主机名:`hostname`"
    echo "IP地址:`ip a | grep "global" | cut -d "/" -f 1 | cut -d "t" -f 2 | tr -d " "`"
    echo "操作系统版本:`cat /etc/redhat-release`"
    echo "内核版本:`uname -r`"
    echo "CPU信息:`lscpu | grep -i "Model name" | cut -c "24-69"`"
    echo "内存总大小:`free -h | grep "Mem" | cut -d "M" -f 2 | tr -d "em: "`M"
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test6.sh
    主机名:localhost.localdomain
    IP地址:192.168.80.3
    操作系统版本:CentOS Linux release 7.3.1611 (Core) 
    内核版本:3.10.0-514.el7.x86_64
    CPU信息:Intel(R) Core(TM) i5-4210M CPU @ 2.60GHz
    内存总大小:976M
    ...
    

    实例二:

    #!/bin/bash
    sum=0
    for i in `find / -type f -a -name "*.sh"`
    do
            size=`ls -l $i | cut -d " " -f 5`
            let sum+=size
    done
    echo ".sh结尾的总大小$(($sum/1024))kb"
    ...
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test7.sh
    .sh结尾的总大小1098kb
    

    实例三:创建100个用户并设置6位随机密码

    [root@du ~]# cat test9.sh
    #!/bin/bash
    #!/bin/bash
    for i in `seq 10`
    do
        useradd user$i
        pass=`echo $RANDOM | md5sum | cut -c 1-6`
        echo "$pass" | passwd --stdin "user$i"
        echo -e "账户:user$i
    密码:$pass" >> /root/passwd
    done
    
    ##执行结果:
    
    [root@du ~]# cat passwd
    账户:user1
    密码:69a70a
    账户:user2
    密码:444c02
    账户:user3
    密码:6b381f
    账户:user4
    密码:28d8fd
    

    实例四:找出100以内的质数

    #!/bin/bash
    for i in `seq 100`
    do
        for((j=2;j<i;j++))
        do
             [ $((i%j)) -eq 0 ] &&  break
        done
             [ $j -eq $i ] &&   echo $i
    done
    
    
    ## 执行
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash test.sh 
    2
    3
    5
    7
    11
    13
    17
    19
    23
    29
    31
    37
    41
    43
    47
    53
    59
    61
    67
    71
    73
    79
    83
    89
    97
    

    实例五:逐行读取文件

    #!/bin/bash
    cat $1 | while read line
    do
    echo “$line”
    sleep 1
    done
    
    ## 执行
    
    ╭─root@localhost.localdomain ~  
    ╰─➤  bash readtest.sh /etc/passwd
    “root:x:0:0:root:/root:/bin/zsh”
    “bin:x:1:1:bin:/bin:/sbin/nologin”
    “daemon:x:2:2:daemon:/sbin:/sbin/nologin”
    “adm:x:3:4:adm:/var/adm:/sbin/nologin”
    “lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin”
    ^C#  
    

    实例六:shell脚本工整化输出,表格形式输出
    摘自:https://blog.csdn.net/qq_41228463/article/details/80720772

    #!/bin/bash
    table=""
    #设置行,可以是表头,也可以是表格内容。
    #如果是表格内容,“—”表示空值
    function setRow(){
        value=$*
        table=${table}"|${value// /#|}#|
    "
    }
    
    #行分隔线
    #入参:表格的列数。如表格有5列,则入参为5
    function splitLine(){
        local num=`expr $1 + 2`
        split=`seq -s '+#' $num | sed 's/[0-9]//g'`    # 生成连续个的+#
        table=${table}"${split}
    "
    }
    
    #绘制表格
    #入参:table
    function setTable(){
        echo -e $1|column -s "#" -t|awk '{if($0 ~ /^+/){gsub(" ","-",$0);print $0}else{print $0}}'
    }
    if [ "$SHLVL" -eq "2" ]
    then
       table=""
        splitLine 3
        setRow "姓名" "性别" "年龄"
        splitLine 3
        setRow "Tom" "male" "10"
        setRow "Nacy" "female" "-"
        splitLine 3
        setTable ${table}
    fi
    
    ##输出结果
    
    #bash test.sh
    +------+--------+------+--
    |姓名  |性别    |年龄  |
    +------+--------+------+--
    |Tom   |male    |10    |
    |Nacy  |female  |-     |
    +------+--------+------+--
    

  • 相关阅读:
    Activity生命周期 onCreate onResume onStop onPause (转)
    职场链接
    memset中的sizeof
    c文件操作 (转)
    串口编程 tcflush()函数 (转)
    tcflush 功能(转)
    串口开发(转)
    ios github网址
    做移动端视频通话软件,大致看了下现有的开源软件(转)
    PJSIP框架
  • 原文地址:https://www.cnblogs.com/du-z/p/10959937.html
Copyright © 2011-2022 走看看