• 20201220蔡笃俊《信息安全系统设计与实现》第十章学习笔记


    一、任务内容

    • 自学教材第10章,提交学习笔记(10分)

    • 大家学习过Python,C,Java等语言,总结一下一门程序设计语言有哪些必备的要素和技能?这些要素和技能在shell脚本中是如果呈现出来的?

    • 知识点归纳以及自己最有收获的内容 (3分)

    • 问题与解决思路(2分)

    • 实践内容与截图,代码链接(3分)

    • ...(知识的结构化,知识的完整性等,提交markdown文档,使用openeuler系统等)(2分)

    二、知识点归纳以及自己最有收获的内容

    1.知识点归纳

    在这之前,我们要先了解一下,什么是shell编程?

    高大上的解释,往往让人摸不住头脑。一句话概括就是:shell编程就是对一堆Linux命令的逻辑化处理。sh脚本是一个包含sh语句的文本文件,命令解释程序sh要执行该语句;C程序与其在根本上是不同的。首先,sh是一个解释程序,逐行读取sh脚本文件并直接执行这些行,相反,C程序必须先编译链接到一个二进制可执行文件,然后通过主sh的子进程运行二进制可执行文件;其次,在C程序中,每个变量必须有个类型,相反,在sh脚本中,每个变量都是字符串;最后,每个C程序必须有一个main()函数,每个函数必须定义一个返回值类型和参数,相反,sh脚本不需要main函数。

    我们可以从最基本的sh脚本开始:

    #!/bin/bash    # 这句话表示用linux指定去解析文本内容
    #第一个shell小程序
    echo hello world!
    
    
    • 第一行表示我们选择使用bash shell。shell中#符号表示注释。shell的第一行比较特殊,一般都会以#!开始来指定使用的shell类型。在linux中,除了bash shell以外,还有很多版本的shell, 例如zsh、dash等等…不过bash shell还是我们使用最多的。

    • 第二行以#符号开始,表示本行是注释,运行的时候是不会运行本行的。

    • 第三行中的echo是linux中的输出命令,该行的意思很明显的就是输出hello world!

    • chmod +x hello.sh 的意思是赋予hello.sh的可执行权限

    • 在linux中,后缀名几乎是可以任意的或者没有后缀名,一般将shell保存为xxx.shell是为了看起来更直观

    了解了最基本的sh编程,让我们开始深入了解sh吧!

    1. 命令行参数

    • $#=命令行参数\(1到\)n的数量;
    • $*=所有命令行参数,包括$0;
    • 此外,sh还有与命令执行相关的以下内置变量:
    • $S=执行sh进程PID;
    • $?=最后一个命令执行的退出状态(如果成功,则为0,否则为非0)

    2. sh变量

    在sh中,什么是变量?

    变量是计算机内存的单元,其中存放的值可以改变。当Shell脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中。每个变量有一个名字,所以很容易引用它。使用变量可以保存有用信息,使系统获知用户相关设置,变量也可以用户保存暂时信息。
    shell编程中,我们可以把变量分成两种,一种是我们自己定义的变量(自定义变量),可以通过set命令查看系统变量;第二种是Linux已定义的环境变量(如 PATH,HOME,TERM等等……这类变量我们可以直接使用)需要记住的是:变量设置要遵循变量设置规则,定义变量不用[$]符号,使用变量加符号即可。

    变量设置规则

    * 变量名称可以由字母、数字和下划线组成,但不能以数字开头。
    * 变量的默认类型都是字符串型
    * 变量用等号连接值,等号左右两侧不能有空格。
    * 变量的值如果有空格,需要使用单引号或者双引号苦括起来。
    * 不能使用标点符号
    

    3. sh中的引号

    sh有许多特殊字符,如S、/、*、>、<等。要想把它们用作普通字符,可使用\或单引号来引用它们。通常,‘\’用于引用单个字符。单引号用于引用长字符串。单引号内没有替换。双引号用于保留双引号字符串中的空格,但在双引号内会发生替换。

    4. sh语句

    sh语句包括所有Unix/Linux命令,以及可能的I/O重定向。此外,sh编程语言还支持控制sh程序执行的测试条件、循环、case等语句。此外,sh编程语言还支持控制sh程序执行的测试条件、循环、case等语句。

    5. sh命令

    • 内置命令

      • .file:读取并执行文件。
      • break [n]:从最近的第n个嵌套循环中退出。
      • cd [dirname]: 更换目录。
      • continue[n]:重启最近的第n个嵌套循环。
      • eval [arg...]:计算一次参数并让sh执行生成的命令。
      • exec [arg...]:通过这个sh执行命令,sh将会退出。
      • exit [n]:使sh退出,退出状态为n。
      • export [var…]:将变量导出到随后执行的命令.
      • read [var...]:从stdin 中读取一行并为变量赋值。
      • set [arg...]:在执行环境中设置变量。
      • shift:将位置参数$2 $3...重命名为 $1 $2...。
      • trap [arg] [n]:接收到信号n后执行参数。
      • umask [ddd]:将掩码设置为八进制数 ddd 的。
      • wait pid]: 等待进程 pid,如果没有给出pid,则等待所有活动子进程。
    • Linux命令

      • echo命令:将参数字符串作为行回显到stdout。
      • expr命令:间接更改sh变量的值。
      • 管道命令:作为过滤器。
      • 实用命令:
        • axk:数据处理程序。
        • cmp:比较两个文件。
        • comm:选择两个排序文件共有的行。
        • grep:匹配一系列文件的模式。
        • diff:找出两个文件的差异。
        • join:通过使用相同的键来连接记录以比较两个文件。
        • sed:流或行编辑命令。
        • sort:排序或合并文件。
        • tail:打印某个文件的最后口行。
        • tr:一对一宇符翻译。
        • uniq:从文件中删除连续重复行。

    6. sh命令替换

    在sh中,\(A会被替换成A值。同样,当sh遇到‘cmd’或\)(cmd)时,它会先执行cmd,然后用执行的结果字符替换$(cmd)。

    7. sh控制语句

    • if语句

      • if条件语句

        if [ 条件判断 ];then
        程序
        fi
        

        或者

        if [ 条件判断 ]
          then
            程序
        fi
        

        实践:

        #!/bin/bash
        
        #统计根分区使用率
        rate=$(df -h | grep /dev/vda1 | awk '{print $5}' | cut -d "%" -f 1)
        
        if [ $rate -ge 20 ]
          then
        echo "error 10"
        fi
        
      • if else条件语句

        if [ 条件判断 ]
          then
            条件成立时,执行此程序
          else
             条件不成立时,执行的另外一个程序
        fi
        

        实践:

        #!/bin/bash
        
        #备份mysql数据库
        
        #同步系统时间
        ntpdate asia.pool.ntp.org &>/dev/null
        #把当前系统时间按照“年月日”格式赋予变量date
        date=$( date+%y%m%d )
        #统计mysql的数据库大小,并把大小赋予size变量
        size=$( du -sh /var/lib/mysql )
        
        if [ -d /tmp/dbback ]
          then
            echo "Date: $date!" > /tmp/dbback/dbinfo.txt
            echo "Date size: $size" >> /tmp/dbback/dbinfo.txt
            cd /tmp/dbback
            tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>/dev/null
            rm -rf /tmp/dbback/dbinfo.txt
         else
            mkdir /tmp/dbback
            echo "Date: $date!" > /tmp/dbback/dbinfo.txt
            echo "Date size: $size" >> /tmp/dbback/dbinfo.txt
            cd /tmp/dbback
            tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>/dev/null
            rm -rf /tmp/dbback/dbinfo.txt 
        fi
        
      • 多分支if条件语句

         if [ 条件判断式1 ]
          then
            当条件判断式1成立时,执行程序1
         elif [ 条件判断式2 ]
            then
          当条件判断式2成立时,执行程序2
        ...省略更多条件
        else 
        当所有条件都不成立时,最后执行此程序
        fi
        

        实践:

        #!/bin/bash
        
        #接收键盘输入,并赋予变量file
        read -p "Please input a filename: " file
        
        #判断file变量是否为空
        if [ -z "$file" ]
          then
            echo "error,请输入文件名"
            exit 1
        #判断file的值是否存在
        elif [ ! -e "$file" ]
          then
            echo " 你的文件不存在"
            exit 2
        #判断file的值是否为普通文件
        elif [ -f "$file" ]
          then
            echo "文件是普通文件"
        #判断file的值是否为目录文件
        elif [ -d "$file" ]
          then
          echo "文件是目录文件"
        else
          echo "文件是其他类型的"  
        fi
        
    • case语句

       case $变量名 in
        "值1")
            如果变量的值等值1,则执行程序1
            ;;
         "值2")
            如果变量的值等值2,则执行程序2
            ;;    
          ……省略其他分支
          *)
             如果变量的值都不是以上的值,则执行程序
             ;;
      esac
      

      实践:

      #!/bin/bash
      #测试case语句
      
      echo "如果想去上班,请输入“1”"
      echo "如果不想上班,请输入“2”"
      echo "如果想居家办公,请输入“3”"
      
      read -t 30 -p "请输入你的选择:" choose
      
      case "$choose" in
              "1")
                      echo "想去上班!"
                      ;;
              "2")
                      echo "不想去上班!"
                      ;;
              "3")
                      echo "居家办公!"
                      ;;
              *)
                      echo "只能输入1或者2或者3"
                      ;;
      esac
      
    • for循环

    语法一

    for 变量 in 值1 值2 值3...
      do
        程序
      done
    

    实践:

    #!/bin/bash
    #打印1??6的循环
    for i in 1 2 3 4 5 6
            do
                    echo $i
            done
    

    语法二:

    for (( 初始值;循环控制条件;变量变化 ))
      do
        程序
      done
    

    实践:

    #!/bin/bash
    #使用for循环计算1-100的和
    s=0
    for (( i=1;i<=100;i=i+1 ))
            do
                    s=$(( $s+$i ))
            done
                    echo "$s"
    
    
    #!/bin/bash
    #批量添加指定数量的用户
    
    read -t 30 -p "Please input user name:" name
    read -t 30 -p "Please input the mumber of users:" num
    read -t 30 -p "Please input the password of users:" pass
    
    if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ]
            then
            y=$(echo $num | sed 's/[0-9]*$'//g)
                    if [ -z "$y" ]
                    then
                    for (( i=1;i<=$num;i=i+1 ))
                     do
                            /usr/sbin/useradd $name$i &>/dev/null
                            echo $pass | /usr/bin/passwd --stdin $name$i &>/dev/null
                     done
                    fi
    fi
    
    • while循环

    while循环是不定循环,也称条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止,这就和for的固定循环就不太一样了。

    while [ 条件判断式 ]
      do
        程序
      done
    

    实践:

    #!/bin/bash
    #从1加到100 
    
    i=1
    s=0
    
    while [ $i -le 100 ]
    #如果变量i的值小于等于100,则执行循环 
    	do
    		s=$(( $s+$i ))
    		i=$(( $i+1 ))
    	done
    	echo "The sum is: $s"
    
    • unit循环

    until循环,和while循环相反,until循环时,只要条件判断式不成立,则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。

    #!/bin/bash
    #从1加到100
    
    i=1
    s=0
    
    until [ $i -gt 100 ]
    #循环直到变量i的值大于100,循环就停止了 
    	do
    		s=$(( $s+$i ))
    		i=$(( $i+1 ))
    	done
    	echo "The sum is : $s "
    

    8. continue和break语句

    break命令允许跳出所有循环(终止执行后面的所有循环)。
    continue命令不会跳出所有循环,仅仅跳出当前循环。
    

    9. I/O重定向

    >file stdout转向文件,如果文件不存在,将会创建文件
    >>file stdout追加到文件
    <file 将文件用作stdin;文件必须存在具有r权限
    <<word 从“here”文件中获取输入,直到包含“word”的行
    

    输入重定向:

    [root@localhost ~]# wc [选项][文件名]
    选项:
    -c   统计字节数
    -w   统计单词数
    -l   统计行数
    

    10. sh中的通配符

    • file *:列出当前目录中所有文件的信息
    • ls *.c:列出当前目录中所有以.c结尾的文件
    • ?通配符:查询某文件名中的字符
    • []通配符:查询文件名中一对[]中的字符
    • file [ab]:包含字符a或b的所有文件名
    • ls [xyz]:列出所有包含x、y或z的文件名
    • ls [a-m]:列出包含a到m范围内字符的所有文件名

    11. 命令分组

    在sh脚本中,可以用{}或()对命令进行分组。{ls;mkdir abc;ls;}:通过当前sh执行中的命令列表。命令分组的唯一用处是在相同环境下执行这些命令,例如,为分组中的所有命令重定向L/O。更有用的命令分组是(),由subsh(进程)执行。(cd newdir;ls;A=value;mkdir $A):通过subsh进程执行()中的命令。subsh进程可在不影响父sh的情况下更改其工作目录。此外,当subsh进程终止时,subsh中的任何赋值变量都不起作用。

    12. eval语句

    (1)参数替换:扫描命令行,将任何\(x替换为它的值,但只执行一次,即不能再次替换任何产生的\)符号。
    (2)命令替换:用替换行’pwd’。
    (3)通配符扩展:当sh执行该文件时,它将new*展开为以abc开头的文件名,这些会把所有以abc开头的文件名复制到目标目录中

    2.最有收获的内容

    这一章学习了shell编程,最有收获的就是我们能够利用它就是批处理动作,解放双手,避免重复性劳动。通过对shell的学习让我了解到了脚本的好处:

    • 避免开发人员反复进行一些列重复步骤。比如:联网+检查安装包+安装软件+执行命令,如果经常需要做类似的操作,可以考虑将操作写成脚本; (注:IDE为集成开发环境)
    • 提高编译效率。利用编写好 Makefile 文件(shell 脚本) ,只需要一个 make 命令,整个工程就开始自动编译。因为 Makefile 文件中已经事先指明了源文件的编译顺序、依赖关系等重要的编译信息;
    • 不依赖 IDE 就可以实现功能编码, 这在陌生的机器(不具备安装软件的权限) 上显得尤为重要;
    • 方便调用机器下的所有资源。 类似于胶水一样,可以将各类资源(命令、程序、脚本等) 拼接在一起使用。

    3. 思维导图

      \#! /bin/bash
      echo \$# = $#
      echo \$* = $*
      echo $1 $9 $10
      echo $1 $9 ${10}
      shift
      echo $1 $9 ${10}
      ~                   
    
    

    三、一门程序设计语言有哪些必备的要素和技能?这些要素和技能在shell脚本中是如果呈现出来的?

    一种编程语言基本上包括:

    • 数据类型
    • 运算符
    • 控制语句

    其中数据类型包括:基本类型,集合类型,有了数据类型,才有变量的存在。shell常用的数据类型有 字符串、整数型、数组。
    运算符:计算机的本质就是运算,而写程序,也是为了帮助人去计算,所以一种编程语言肯定有运算符。Shell 和其他编程语言一样,支持多种运算符,包括:算数运算符、关系运算符、布尔运算符、字符串运算符、文件测试运算符。
    控制语句:人类社会发生的事情,都是有条件的,存在即为正确,因为有它存在的条件。所谓控制语句也就是设定一个条件,当某一个条件发生了,会发生什么事情。shell的控制语句在上方已经明确说明了,这里就不详细阐述了。

    四、问题与解决思路

    最开始在运行sh脚本时,出现了这个错误:-bash: ./test.sh: 权限不够
    我反复校对了网上和我的代码,是一模一样的,但是为什么我的就报错呢?
    解决办法:后来查阅资料才发现,问题出在shell脚本上。windows下编译的shell文件,每一行的结尾是\n\r,而在linux下文件的结尾是\n,这个一般用肉眼是看不出来的。利用正则表达式把以\r结束的字符换成空白:

    sed -i 's/\r$//'  *.sh       //利用通配符,特别高效
    
    

    成功解决。

    五、实践过程

    运行myth脚本,成功执行

    尝试条件判断语句

    #!/bin/bash                                                                     
    
    read -p "请输入小于100的整数:" num
    
    if [ $num -eq 1 ];then
    
      echo "和等于: $num"
    
    sum=0
    
    elif [ $num -gt 1 ] && [ $num -lt 100 ];then
    
      for ((i=1; i<=$num; i++))
    
      do
    
      let sum=$sum+$i
    
      done
    
      echo "1到$num的和为$sum"
    
    

  • 相关阅读:
    OpenCV中的绘图函数
    整理不错的opencv博客
    opencv中的函数
    这是一个学习前端技术的网站
    HDU1520 Anniversary party(树形DP入门)
    CF1255C League of Leesins(图论)
    HDU4725 The Shortest Path in Nya Graph(最短路分层)
    1288C Two Arrays
    CF1294D MEX maxiszing
    CF1295C Obtain the String
  • 原文地址:https://www.cnblogs.com/acacacaac/p/16704427.html
Copyright © 2020-2023  润新知