• 变量,元字符,流程判断if,while、for循环


    一: shell编程介绍

    1、一个shell脚本运行必须要拥有r和x权限; chamod u+x 1.txt

    2、运行一个shell脚本的3个步骤:

    (1)启动bash解释器

    (2)bash把文件内容从硬盘读入内存

    (3)bash把读入到内存的内容进行语法解释,控制操作系统执行shell代码

    写脚本时候,应该规避好一些交互式的命令

    3、运行脚本的有2中方法:

    ​ (1)交互式环境:每敲一个命令执行一次,但是不能永久保存

    ​ (2)文件内:一次全部执行,但是会永久保存

    4、在当前界面运行脚本,不开启新进程

    . 1.txt 在当前进程 或者 source 1.txt

    bash 1.txt 开启了一个新进程

    ./ 1.txt 开启了新的一个进程

    二:变量

    1、变量的定义
    变量需要先定义,后引用
    per=36                                     #定义变量的时候,=两边不能有空格,否则报错       @@@
    echo $per
    echo ${per}G                               # 引用变量最好用这样的格式              @@@
    
    2、变量名的使用规则
    用字母,数字,下划线组成;不可用中文,以及一些既有的命令
    
    3、变量值的类型
    int整型       name=10
    fault浮点型   name=3.14
    str字符串     name="hello world"
    
    4、特殊的符号                                                                  @@@@
    "":双引号 
    '':单引号的硬引用; 引号内的符号均无特殊意义
    ``:取里面命令的结果
    $():取里面命令的结果,区别于上条的是,本条可以进行嵌套:
    	$(命令 $(命令))
    :右斜杠
    
    例子:
    a=10
    echo "$a"       #结果是10
    echo '$a'       #结果是$10
    echo "$a"      #结果是$a                        #取消特殊字符的意义
    echo $(+date %Y-%m-%y).txt
    
    5、变量的作用域(生效范围)
     (1)全局变量:定义的变量只在该进程有效
     例子:
     per=36
     vim 1.txt (echo "$per")
     echo "$per"                           #有结果
     bash 1.txt                            #没有结果
     source 1.txt                          #有结果
     export per ; bash 1.txt               #有结果    (继承了per的结果给子进程,父进程看不到)  @@@@
       export的是遗传,子子孙孙进程都可以看待;但是子进程开启的变量,父进程不可以引用;
      
      
     (2)变量先从局部变量找,没有了再从父辈遗传的找,再从环境变量里找
     	
     (3)添加环境变量                                             #登录时候就自动启动
     	 * 对/root 临时添加环境变量           PATH=$PATH:/root          
     	 * 对/root 永久添加环境变量,并给到所有的子进程
     	 	vim /etc/profile  
     	 	   PATH=$PATH:/root
     	 	   export PATH
         env  查看所有的环境变量
         set  查看所有的变量,临时的也可以看到
     
      (4)删除变量
       unset per         
    

    三:元字符(一些特殊符号)

    元字符是被shell解释器解释,而正则表达式是被命令解释

    1、{}、[]和!的应用:
    touch {1..5}.txt
    touch {a..e}.txt
    ls [0-9].txt
    ls [!0-9].txt
    
    2、变量间的运算
      
     (1)整型和浮点型的运算
      ***expr 变量间不做什么的情况下只是整型int的运算
         $a + $b               特别注意中间的空格                                      @@@@@ 
     			c=`expr $a + $b`
         expr 支持 + - / % 除的话取整数,%为取余                                        @@@@@
         乘法是:expr 5 * 3                                                         @@@@@
      ***bc
      	echo " 3.14 < 3.16 " | bc    
      	
     (2)let x++  等于在原来变量上加1不支持多加  没有此变量时候默认就为0
        a=10;  echo `expr $a + 1 `
     (3)&
       1个&放在命令的结尾表示后台运行
       2个&&放在2个命令之间,表示并且的意思;只有左边的命令成功的情况下才可以运行右边的命令
       &> 无论结果是否正确都重定向
     (4)|| 或者的意思
       wssfsf || ls     左边命令错误时,右边命令才运行; 也就是要不左边成立,要不右边成立
       ls || pwd        此时只运行ls命令
     (5);
       不管命令是否正确都会运行
       asfg ; pwd
     (6)()
       *取命令的结果:echo $(expr $a + $b)
       *嵌套取命令结果,或者进行运算:$(命令 $(命令)) 
        > >=  < <=  
        ==(等于)
        !=(不等于)
        &&(and)
        ||(or)
        例子:
            x=100   
            (( $x == 100 )) ; echo $?                                 #结果是1
            (( $x != 100 || 100 >= 10 )) ; echo $?                    #结果是0
        
     (7)[]  类似于test命令
     *test
       test $x -eq 5 ; echo $?
     *[]
       *进行整型运算:echo $[10 + 2]
       *进程过滤时候:ps -aux | grep [p]ing   去掉这个命令执行时候的进程
       *判断字符值是否相同;例子如下
       		name="egon" ; [ $name = "egon" ]
       		echo $?     #结果为0是真,结果为1是假的
       	 **小脚本(用户登录程序:要求只有用户名和密码对输出ok,其他ng):
       	   [root@local-test var]# cat 1.txt 
             #!/bin/bash
             read -p "yourname:" name
             read -p "passwd:" passwd
             [ $name = "zzyy" ] && [ $passwd = 123 ] && echo ok || echo NG
       *判断数字值是否相同;例子如下                                                     @@@@@
            *判断数字值相等:[ 10 -eq 10 ] && echo $?     结果是0
            *判断数字值大于:[ 10 -gt 8 ] && echo $?      结果是0
            *判断数字值大于等于:[ 10 -ge 12] ; echo $?    结果是1
            *判断数字值小于:[ 10 -lt 8 ] ; echo $?       结果是0
            *判断数字值小于等于:[ 10 -le 12] ; echo $?    结果是1
            *判断数字值不等于:[ 10 -ne 12] ; echo $?    结果是0
            *判断是否有一般文件:[ -f /root/2.txt ] ; echo $?    判断是否有这个普通文件2.txt
            *判断是否有这个文件:[ -e /root/2.txt ] ; echo #?    判断是否有这个文件2.txt
            *
      (8)? 指定一个字符
        ls ?.txt ; ls ??txt
        查找所有a到Z的文件  ls /etc/[a-Z].txt 
      (9) : 结果永远为真
          : ; echo $?    #结果是0
          
    总结:
    ;   不管左右的命令是否成功都运行,错误就报错
    &&  只有左边的成功时,右边的才会运行
    ||  或者左边的运行。或者右边的运行
    
    3、如何进行小数的运算
     (1)yum install bc -y
     (2)echo $(echo "scale=2; 3/10" | bc  | cut -d '.' -f2 )%                        @@@@@
             结果:30%
         scale=2取小数点两位,后执行命令3/10,后bc做小数,后以.分割取出来点后的2位数字
         echo " 3.14 < 3.16 " | bc   
    
    4、awk和bc的小例子
    a=free | awk 'NR==2{print $NF}'      #拿出实际使用的内存    awk必须是单引号
    b=free | awk 'NR==2{print $2}'       #总的内存
    echo $(echo "scale=2; $a / $b " | bc | cut -d '.' -f2)%   #计算出%比
    echo `echo "scale=2; $a / $b " |bc | cut -d "." -f2 `%
    
    写脚本的时候注意事项:
    对数据的增改删的时候需要
    (1)set -o errexit      脚本有错误的时候不运行退出
         [root@local-test ~]# cat 1.txt 
            #!/bin/bash
            set -o errexit
    
            echo 111
            echo 222
            echo 333
            afsdfgdg
            echo 444
         [root@local-test ~]# bash 1.txt
            111
            222
            333
            1.txt: line 7: afsdfgdg: command not found  
         
         
    (2)set -o nounset      只要变量不存在就退出   echo $yyy  yyy之前不被定义
    
    (3)set -o pippefail    addsv| echo 123
    
    egon--元字符总结
    
    1、`` 与$():取命令的结果
        [root@localhost ~]# echo `pwd`
        /root
        [root@localhost ~]# echo $(pwd)
        /root
        ​
        不一样的地方在于$()可以嵌套,而``不能嵌套
        [root@localhost ~]# echo $(ls $(pwd))
        ​
        # 练习
        [root@aliyun test]# touch $(date +%F)_bak.tar.gz
        [root@aliyun test]# ls
        2020-08-24_bak.tar.gz
    
    2、~家目录
    3、.与..
    4、!调用历史命令、取反
        # 1、调用历史命令
        [root@egon ~]# !1066
        [root@egon ~]# !ls # 匹配最近的一次历史命令
        ​
        # 2、取反1:对命令的结果取反
        [root@egon ~]# ! pwd
        /root
        [root@egon ~]# echo $?
        1
        ​
        # 3、取反2:效果与^雷同
        [root@localhost ~]# touch /test/{1.txt,2.txt,a.txt,aaa_bbb.txt}
        [root@localhost ~]# find /test ! -name 1.txt
        /test
        /test/2.txt
        /test/a.txt
        /test/aaa_bbb.txt
        ​
        [root@localhost ~]# ls /test/[!0-9].txt # .txt前只有一个字符,但是非数字
        /test/a.txt
        [root@localhost ~]# ls /test/[^0-9].txt # .txt前只有一个字符,但是非数字
        /test/a.txt
        ​
        [root@aliyun test]# ls -a /etc/skel/.[!.]*
    5、@无特殊意义
    6、#注释
    7、$取变量值
    (1)[root@localhost ~]# x=1
        [root@localhost ~]# echo $x
    (2)%、-、+运算符,注意%可以与jobs配合“kill %工作号”杀后台进程。-减号还有区间及cd -回到上一级的意思
        # 数学运算
        # 1、bc是比较常用的linux计算工具了,而且支持浮点运算:
        [root@localhost ~]# res=`echo 1+1 | bc`
        [root@localhost ~]# res=`echo 1.2+1.3|bc`
         [root@localhost ~]# res=`echo "scale=2;5.0/3.0"|bc`
        [root@localhost ~]# echo $res
        2 取余
        [root@localhost ~]# res=`echo 10 % 3 | bc`
        [root@localhost ~]# echo $res
        [root@localhost ~]# res=`echo 5.0+3.0|bc`
        [root@localhost ~]# echo $res
        3、expr不支持浮点数计算。而且要注意数字与运算符中的空格
        [root@localhost ~]# res=`expr 5 / 3` # 不支持浮点计算
        [root@localhost ~]# echo $res
        [root@localhost ~]# res=`expr 1+1` # 注意:要有空格
        [root@localhost ~]# echo $res
        [root@localhost ~]# res=`expr 1 + 1`
        [root@localhost ~]# echo $res
        [root@localhost ~]# res=`expr 5 * 3` # 在expr中*号要转义才能用,否则报语法错
        4、$(()) 同expr,不支持浮点数运算
        [root@localhost ~]# echo $((1+1))
        [root@localhost ~]# echo $((1.0+2.0))
        -bash: 1.0+2.0: 语法错误: 无效的算术运算符 (错误符号是 ".0+2.0")
    
        5、$[]同expr以及$(()),不支持浮点运算
        [root@localhost ~]# x=1
        [root@localhost ~]# echo $[$x+1]
        6、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"
        [root@aliyun test]# x=1
        [root@aliyun test]# let x+=10
        [root@aliyun test]# echo $x
        11
    8、^同!一样
    9、&后台运行
        [root@localhost home]# echo "hello";sleep 3;echo "world" &
        && 两个命令之间,前面那个运行成功后面才运行
    10、*任意多个字符
        [root@localhost ~]# touch 1.txt 2.txt aa.txt aaa.txt
        [root@localhost ~]# rm -rf *.txt
        [root@localhost ~]# touch 1.txt 2.txt aa.txt aaa.txt a1c.txt
        [root@localhost ~]# ls *.txt
        1.txt 2.txt a1c.txt aaa.txt aa.txt
    11、()在子shell中执行
        [root@localhost ~]# (x=1)
        [root@localhost ~]# echo $x
        应用
        [root@localhost ~]# (umask 066;touch a.txt) # umask的设置只在子shell中有效
        [root@localhost ~]# ll a.txt
        -rw-------. 1 root root 0 8月 13 15:22 a.txt
        [root@localhost ~]# touch b.txt
        [root@localhost ~]# ll b.txt
        -rw-r--r--. 1 root root 0 8月 13 15:23 b.txt
        10、_下划线:无特殊意义,可以用于名字的声明
        [root@localhost ~]# tar -czvf `date +%F_%H:%M:%S`_bak.tar.gz /etc/
        11、=赋值,==判断相等性
        [root@localhost ~]# [ 1 == 1 ] # 条件1 == 1的左右两边必须有空格
        [root@localhost ~]# echo $? # 判断上一条命令的结果是否为真,0=》true
        0
    12、|管道:把一个进程的处理结果传递给另外一个进程
        [root@localhost ~]# ps aux | grep python
        |管道命令的作用,是将左侧命令的标准输出转换为标准输入,提供给右侧命令作为参数。但是,大多数命令都不接受标准输入作为参数,只能直接在命令行输入参数,这导致无法用管道命令传递参数。比如echo命令就不接受管道传参。
        $ echo "hello world" | echo
        xargs命令的作用,是将标准输入转为命令行参数,例如
        $ echo "hello world" | xargs echo
        hello world
        [root@localhost ~]# find /home/ -type d -name "test*" |xargs ls
        1.txt 2.txt 3.txt
        [root@localhost ~]# ls /home/test
        1.txt 2.txt 3.txt
    13、转义特殊字符
        [root@localhost ~]# mkdir a b.txt # 虽然可以,但不推荐
        [root@localhost ~]# ll
        总用量 0
        drwxr-xr-x. 2 root root 6 8月 13 15:35 a b.txt
    
        ​
        [root@localhost ~]# echo $RMB # 默认会当成变量
        ​
        [root@localhost ~]# echo '$RMB' # 取消特殊意义
        $RMB
        [root@localhost ~]# echo $RMB # 取消特殊意义
        $RMB
    14、[]条件测试,后续会详细介绍
        [root@localhost ~]# name="egon"
        [root@localhost ~]# [ $name == "egon" ];echo $?
        0
        [root@localhost ~]# name="adf"
        [root@localhost ~]# [ $name == "egon" ];echo $?
        1
        ​
        [root@localhost ~]# [ -d /test ];echo $?
        0
        [root@localhost ~]#
    15、引号
        '' 强引用(在单引号中都视为普通字符)
        " " 弱引用 (在双引号中保留变量)
        ​
        [root@localhost ~]# x=111
        [root@localhost ~]# echo "$x"
        111
        [root@localhost ~]# echo '$x'
        $x
        [roo
    16、;与&&与||连接多条命令
        [root@localhost home]# gagaga;ls # 不论前一条命令运行成功与否,都会执行后续命令
        bash: gagaga: 未找到命令...
        egon
        [root@localhost home]# gagaga && ls # 只有前一条命令执行成功,才会执行后续命令
        bash: gagaga: 未找到命令...
    
        [root@localhost home]# ls /test || mkdir /test # 前一条命令执行不成功才会执行后续命令
        0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
    17、:空命令,真值
        [root@egon ~]# :
        [root@egon ~]# echo $?
        0
    18、/路径分隔符
    19、{}循环列表
        [root@localhost home]# touch /test/{0..9}.txt
        [root@localhost home]# ls /test/
        0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
        ​
        [root@localhost ~]# touch {1..3}{a..d}.txt
        [root@localhost ~]# ls
        1a.txt 1b.txt 1c.txt 1d.txt 2a.txt 2b.txt 2c.txt 2d.txt 3a.txt 3b.txt 3c.txt 3d.txt
        ​
        [root@egon ~]# x=100
        [root@egon ~]# echo ${x}% # 控制变量名的范围
        100%
        [root@egon ~]#
        [root@egon ~]# echo $xrmb
        ​
        [root@egon ~]# echo ${x}rmb
        100rmb
    20、重定向
        > >> 输出重定向
        < << 输入重定向
        ​
        > 覆盖 >> 追加
        [root@localhost home]# cat >> a.txt << EOF
        > 111
        > 222
        > 333
        > EOF
        ​
        0标准输入、1标准正确输出、2标准错误输出,&标准正确和错误输出
        [root@localhost home]# pwd 1>a.txt
        [root@localhost home]# cat a.txt
        /home
        [root@localhost home]# gagag 2>a.txt
        [root@localhost home]# cat a.txt
        bash: gagag: 未找到命令...
        [root@localhost home]# gagaga &>/dev/null
        ​
        < << 输入重定向
        [root@localhost ~]# mysql -uroot -p123 < bbs.sql
        [root@localhost home]# grep root < /etc/passwd
        root:x:0:0:root:/root:/bin/bash
        operator:x:11:0:operator:/root:/sbin/nologin
        ​
        [root@localhost home]# dd if=/dev/zero of=/a.txt bs=1M count=10
        记录了10+0 的读入
        记录了10+0 的写出
        10485760字节(10 MB)已复制,0.024387 秒,430 MB/秒
        [root@localhost home]# dd </dev/zero >/b.txt bs=1M count=10
        记录了10+0 的读入
        记录了10+0 的写出
        10485760字节(10 MB)已复制,0.0202365 秒,518 MB/秒
        ​
        [root@localhost home]# ll /a.txt
        -rw-r--r--. 1 root root 10485760 8月 13 16:02 /a.txt
        [root@localhost home]# ll /b.txt
        -rw-r--r--. 1 root root 10485760 8月 13 16:03 /b.txt
    21、?任意一个字符
        [root@localhost ~]# ls ??.txt
        aa.txt
        [root@localhost ~]# ls a?c.txt
        a1c.txt
        [root@localhost ~]# rm -rf *.txt
        22、范围中的任意一个字符 [12] [ac] [a-z] [0-9]
        [root@localhost ~]# touch a1c a2c axc aXc axd
        [root@localhost ~]# ls a?c
        a1c a2c axc aXc
        [root@localhost ~]# ls a[1x]c
        a1c axc
        [root@localhost ~]# ls a[a-z]c
        axc aXc
        [root@localhost ~]# ls a[A-Z]c # 不区分大小写
        axc aXc
        [root@localhost ~]# ls a[x]c
        axc
        [root@localhost ~]# ls a[X]c
        aXc
        [root@localhost ~]# ls a[0-9]c
        a1c a2c
        [root@localhost ~]# ls /dev/sd[a-z]*
        /dev/sda /dev/sda1 /dev/sda2 /dev/sda3 /dev/sdb1
    

    三:流程控制之if判断

    if的语法:
    什么是if判断,为什么要用?
    根据条件的真假来决定去做什么事情,要用是因为要让计算机代替人去做判断
    1. 语法
     ***完整语法
    	if 条件 ; then            # 如果条件是命令,一般把它丢到空里/dev/null
    		代码1                 #如果条件1成立下面的elif不允许
    		代码2 
    	elif 条件 ; then          #如果条件1不成立,本条件运行
    		代码1
    		代码2
    	elif 条件 ; then
    		代码1
    		代码2
    	else
    		代码1
    		代码2
    	fi                                           #if的反过来
    	
     ***单分支语法
        if 条件 ; then
    		代码1
    		代码2
    	fi
    	
     ***单分支语法
        if 条件 ; then
    		代码1
    		代码2
    	else
    		代码1
    		代码2
    	fi      
        
     判断成绩的小例子:
     #!/bin/bash
    read -p "your score:" score
    if [ $score -gt 90 ] ;then
            echo "excellent"
    elif [ $score -ge 60 ] ; then
            echo "good"
    else
            echo "bad"
    fi
    

    四:循环

    while循环
    * true和:表示为真;开始和结束以do和done为准;结束循环可以是自然结束和break
    命令格式:
    while 条件
    do
    命令1
    命令2
    done
    
    (1)脚本中的运行
    登录的小例子:
    #!/bin/bash
    while :
    do
    	read -p "yourname:" name
    	read -p "passwd:" passwd
    	if [ $name = "zz" ] && [ $passwd = 123 ] ; then
    		echo "login ok"
    		break
    	else
    		echo "fluse"
    	fi
    done
    
    打印10以内的数字:
    #!/bin/bash
    count=0                                        #中间不能有空格
    while [ $count -le 10 ]
    do
            echo $count
            (( count ++ ))
    done
    
    
    (2)在命令行中写入一行:
    while 条件 ; do 命令1 ;命令2 ; done        实时显示一些状态
    while true ; do ifconfig; sleep 0.5;clear; done     clear就是清屏
    
    for 循环应用
    for循环在固定循环次数的情况下优势强
    
    
    #!/bin/bash
    for i in `seq 0 3`
    do
        if [ $i -gt 2 ]; then
    
            break
        fi
        echo $i
        
    备注:seq 0 5 和{0..5} 是一个效果;都是0 1 2 3 4 5
    
    ping一个段内的所有网址,看是否ping通
    #!/bin/bash
    for i in {2..100}
    do
    (ping -c1 192.168.15.$i &>/dev/null
    if [ $? -eq 0 ]; then
    	echo "192.168.15.$i up"
    else 
    	echo "192.168.15.$i down"
    fi) &
    done
    
    备注:在命令后加上&,是使其在后台运行,能很大程度的提升运行速度
    

    批量修改文件名

    for name in ls *.txt;do mv $name ${name%.txt}.log;done

    rename log txt *

  • 相关阅读:
    racket eval
    mex不兼容
    【转】雷军 程序员随想
    UBoot 目录结构和编译过程
    远程监控web开发
    STL容器[08]
    STL容器[07]
    STL容器[17]
    STL容器[06]
    stl.map使用总结
  • 原文地址:https://www.cnblogs.com/caodan01/p/14665718.html
Copyright © 2020-2023  润新知