随着科技的发展,软硬件的不断更新。人们通过计算机逐渐从重复性劳动工作中解脱出来,那么计算机如何通过程序执行命令来实现我们预先设定好的步骤呢,请看下图:

 

image

一、我们知道计算机由硬件和软件组成。而软件又分为系统内核跟应用程序;当用户查看一条信息,或者编译一个程序指令,那么他的交互就由计算机通过系统内核调用程序接口,执行单一或者单一指令组成的复杂的程序组成,执行完后,又通过程序接口返回到内核通过输入输出设备呈现在大家面前。

二、程序接口按照他们的语法和编译方式将程序汇编或者调用成系统内核可以识别的指令进行软硬件操作。按照执行方式,分为编译执行和解析执行,按照算法又分为过程编程和对象编程。

1)编译执行:程序语言对写好的程序进行预处理、编译、汇编、链接、完成生成二进制文件由系统和用户来决定是否存贮在硬盘里。代表程序语言有C C++;

2)解释执行:程序语言通过调用系统内部和外部命令文件 、变量、函数、流程语句全程参与实时完成;

3)过程编程:以指令为中心,设计算法,数据服务于算法;

4)对象编程:以数据为中心,设计数据结构(类),程序服务于数据结构。

三、此处我们对编译执行和对象编程暂不做研究,我们今天研究的是解释执行和过程执行中的bash、sed、awk进行简要概述。

   1) 我们都知道编程语言是由语法+(变量+函数+流程控制组成),而变量因在全部的位置不同又分为:

            本地变量:当前shell进程;
            环境变量:当前shell进程及其子进程;
            局部变量:某个函数执行过程;
            位置参数变量:在脚本中引用传递给脚本的参数;  在函数中用传递给函数的参数;
            特殊变量:$?, $*, $@, $#, $$

  2)根据类型分为字符变量和数值变量。

四、变量的命名方式、声明、 引用

  一)命令方式:

  1 、不能以数字开头。

  2、 建议不要以大写字母开头,以免和内置变量冲突。

  3、变量可以包含下划线 但是最好不要以下划线开头。

二)声明:

    1、declare命令用于声明和显示已存在的shell变量。当不提供变量名参数时显示所有shell变量。declare命令若不带任何参数选项,则会显示所有shell变量及其值。declare的功能与typeset命令的功能是相同的。

+/-:"-"可用来指定变量的属性,"+"则是取消变量所设的属性;

-f:仅显示函数;

r:将变量设置为只读;

x:指定的变量会成为环境变量,可供shell以外的程序来使用;

i:[设置值]可以是数值,字符串或运算式。
一般 –i 代表声明的是整数

2. AWK在自定义变量可 –v变量名=变量值在命令行或者程序中直接声明。

三)引用:

   1、bash:

          弱引用: "", 其内部的变量引用会被替换为变量值;
          强引用:'',其变量的变量引用会保持原有字符;
          命令引用:`COMMAND`, $(COMMAND),引用命令的执行结果;

  2、AWk:AWk可以引用shell变量。

    1) 格式如:awk ‘{action}’  变量名=变量值   ,这样传入变量,可以在action中获得值。 注意:变量名与值放到’{action}’后面。‘

   image

   2) BEGIN程序块中变量:awk –v 变量名=变量值 [–v 变量2=值2 …] 'BEGIN{action}’  注意:用-v 传入变量可以在3中类型的action 中都可以获得到,但顺序在  action前面。

   image

五、bash自带的环境变量和awk内置变量

    一、)bash自带的环境变量:

$HOME   #使用者的家目录,可以用cd ~打开

$SHELL   #当前环境使用的SHELL程序,默认是/bin/bash

$PATH   #默认执行程序的路径

$LANG   #语言

$RANDOM   #任意值,编程时很有用,用${RANDOM}可以获取一个范围在0- 32767的任意值。

$PS1   #SHELL提示信息,就是[root@lihan-test-dev02 bashlearn]#  , 用set可以看到PS1='[\u@\h \W]\$ '。PS1内置了一些特殊符号,可以用man bash查看,比如\u是用户名,\h是机器名,\$表示提示字符(root就是#,其他的是$)

$$   #本shell的PID,用echo $$就可以查看

$?   #上一个命令或者函数执行的返回值

$0   #脚 本名字
$1 - $9  #位置参数 (1-9)

${10}  #位置参数 

$#  #位置参数的个数

"$*"  #所有的位置参数(作为单个字符串) 

*"$@"  #所有的位置参数(每个都作为独立的字符串)

${#*}  #传递到脚本中的命令行参数的个数

${#@}  #传递到脚本中的命令行参数的个数

$?  #返回值

$$  #脚本的进程ID(PID)

$-  #传递到脚本中的标志(使用set)

$_  #之前命令的最后一个参数

$!  #运行在后台的最后一个作业的进程ID(PID)

二、)AWK的内置变量

   FS:Field Seperator, 输入时的字段分隔符
        # awk 'BEGIN{FS=":"}{print $1,$7}' /etc/passwd

    RS:Record Seperator, 输入行分隔符
    OFS: Output Field Seperator, 输出时的字段分隔符;
    ORS: Outpput Row Seperator, 输出时的行分隔符;

    NF:Numbers of Field,字段数
    NR:Numbers of Record, 行数;所有文件的一并计数;
    FNR:行数;各文件分别计数;
    ARGV:数组,保存命令本身这个字符,awk '{print $0}' 1.txt 2.txt,意味着ARGV[0]保存awk,
    ARGC: 保存awk命令中参数的个数;
    FILENAME: awk正在处理的当前文件的名称;

六、运算符与表达式

  一) 数学运算符

— +:对两个变量做加法。

— -:对两个变量做减法。

— *:对两个变量做乘法。

— /:对两个变量做除法。

— **:对两个变量做幂运算。

— %:取模运算,第一个变量除以第二个变量求余数。

— +=:加等于,在自身基础上加第二个变量。

— -=:减等于,在第一个变量的基础上减去第二个变量。

— *=:乘等于,在第一个变量的基础上乘以第二个变量。

— /=:除等于,在第一个变量的基础上除以第二个变量。

— %=:取模赋值,第一个变量对第二个变量取模运算,再赋值给第一个变量

   二)字符型运算符:

=:检测两个字符串是否相等,相等返回 true。
[ $a = $b ] 返回 false。

!=:检测两个字符串是否相等,不相等返回 true。
[ $a != $b ] 返回 true。

-z:检测字符串长度是否为0,为0返回 true。
[ -z $a ] 返回 false。

-n:检测字符串长度是否为0,不为0返回 true。
[ -z $a ] 返回 true。

str:检测字符串是否为空,不为空返回 true。
[ $a ] 返回 true。

    三)比较操作符

-eq 检测两个数是否相等,相等返回 true。
[ $a -eq $b ] 返回 true。AWK 为==

-ne 检测两个数是否相等,不相等返回 true。
[ $a -ne $b ] 返回 true。AWK为~

-gt 检测左边的数是否大于右边的,如果是,则返回 true。
[ $a -gt $b ] 返回 false。AWK为<

-lt 检测左边的数是否小于右边的,如果是,则返回 true。
[ $a -lt $b ] 返回 true。AWK 为>

-ge 检测左边的数是否大等于右边的,如果是,则返回 true。
[ $a -ge $b ] 返回 false。AWK为<=

-le检测左边的数是否小于等于右边的,如果是,则返回 true。
[ $a -le $b ] 返回 true。AWK为>=

四)布尔操作符

! 非运算,表达式为 true 则返回 false,否则返回 true。
[ ! false ] 返回 true。

-o 或运算,有一个表达式为 true 则返回 true。
[ $a -lt 20 -o $b -gt 100 ] 返回 true。

-a 与运算,两个表达式都为 true 才返回 true。
[ $a -lt 20 -a $b -gt 100 ] 返回 false。

awk中,任何非0值或非空字符串都为真,反之就为假;

表达式间的逻辑关系符:

&&: 逻辑与

false && true = false
false && false = false

true && false = true
true && true = true

|| :逻辑或

true || true = true
true || false = true

false || true = true
false || false = false
五)文件运算符

        -e $file: 是否存在;存在则为“真”,否则为“假”;
        -a $file: 同上;
        -f $file:文件是否存在且为普通文件;
        -d $file:文件是否存在且为目录;
        -h $file:是否存在且为符号链接文件;
        -L $file: 同上
        -b $file:是否存在且为块设备文件;
        -c $file:是否存在且为字符设备文件;
        -S $file:是否存在且为套接字文件;
        -p $file: 是否存在且为管道文件;

        -r $file: 当前用户对文件是否拥有读权限;
        -w $file:当前用户对文件是否拥有写权限;
        -x $file:当前用户对文件是否拥有执行权限;

        -u $file:文件是否拥有SUID权限;
        -g $file:文件是否拥有SGID权限;
        -k $file:文件是否拥有sticky权限;

        -O $file: 当前用户是否为指定文件的属主;
        -G $file: 当前用户是否为指定文件的属组;

        双目操作符:
        $file1 -nt $file2: file1是否新于file2, file1的最近一次的修改时间戳是否晚于file2的;
        $file1 -ot $file2: file1是否旧于file2, file1的最近一次的修改时间戳是否早于file2的;
        $file1 -ef $file2:file1与file2是否指向了同一个inode;测试二者是否为同一个文件的硬链接;

  六)特殊应用

     1 shell  特殊设备:
        /dev/null: 空,bit buckets,吞下所有数据,并直接丢弃;
        /dev/zero:吐出一堆0;

      shift [n]:位置参数轮替

      2   awk输出重定向:
        print items > output-file
        print items >> output-file
        print items | command

        特殊文件描述符:
        /dev/stdin: 标准输入
        /dev/stdout: 标准输出
        /dev/stderr: 错误输出

     3. shell用户交互命令read

     read命令接收标准输入(键盘)的输入,或者其他文件描述符的输入。得到输入后,read命令将数据放入一个标准变量中.

     -p 选项,允许在read命令行中直接指定一个提示,相当于echo –n;

     -t 选项指定一个计时器,指定read命令等待输入的秒数;

     -n 选项,后接数值表示当输入的字符数目达到预定数目时,自动退出,并将输入的数据赋值给变量。

     -s 选项能够使read命令中输入的数据不显示在监视器上.(文本颜色与背景色相同)

七、流程控制 函数、数组

一)选择判断,条件执行

   1. shell if CONDITION; then
            if-true-分支
        fi

   2. awk 格式:if (condition) {then body} else {else body}

二)多分支 虽然分很多,但是同时执行的只有一个分支。

   1. shell  if CONDITION1; then
                if-CONDITION1-true-分支
            elif CONDTION2; then
                if-CONDITIO2-true-分支
            ...
            else
                if-ALL-false-分支
            fi

           case $VARIABLE in
            PATTERN1)
                分支1
                ;;
            PATTERN2)
                分支2
                ;;
            PATTERN3)
                分支3
                ;;
            ...
            *)
                分支n
                ;;
            esac

   2. AWK  switch (expression) {case VALUE or /RGEEXP/: statement1;... default: stementN}

三) 循环

   1. bash while循环:

            while CONDTION; do
                循环体
            done

            进入条件:当CONDITION为“真”;
            退出条件:当CONDITION为“假”;

            while CONDITION; do
                循环体
                控制变量的修正表达式
            done

           unitl循环:
            until CONDITION; do
                循环体
                循环控制变量的修正表达式
            done

            进入条件:当CONDITION为“假”时
            退出条件:当CONDITION为“真”时

            for循环的用法:
            for ((expr1;expr2;expr3)); do
                循环体
            done

            expr1: 定义控制变量,并初始赋值;
            expr2: 循环控制条件;
                进入条件:控制条件为“真”
                退出条件:控制条件为“假”
            expr3: 修正控制变量

    2.AWK while (condition) {while body}

           do {do-while body} while (condition)

for (variable assignment; condition; iteration process) {for body}

   3.循环控制

             break
            continue

    4.AWK next  提前结束对本行的处理进而提前进入下一行的处理。

三)函数

1.bash 函数

          function: 功能
            把一段具有独立功能代码封装在一起,并给予命名;后续用到时,可直接通过给定函数名来调用整体代码;

            函数作用:
                代码重用;
                模块化编程;

        函数的使用方法:
            先定义:编写函数代码
            后调用:给出函数名,还可按需传递参数

        定义方法:
            (1) function f_name {
                    函数体
                }

            (2) f_name() {
                    函数体
                }

        调用函数:
            f_name [argu1, argu2, ...]

        自定义函数状态返回值:
            return [#]
                0: 成功
                1-255:失败

            注意:函数代码执行时,一旦遇到return,函数代码终止运行,函数返回;

2.AWK函数

             split(string,array[,fieldsep[,seps]]):
            功能:将string表示的字符串以fieldsep为分隔符进行切片,并切片后的结果保存至array为名的数组中;数组下标从1开始;

            root:x:0:0::/root:/bin/bash

            user[1]="root", user[2]

            此函数有返回值,返回值为切片后的元素的个数

            # netstat -tn | awk '/^tcp/{lens=split($5,client,":");ip[client[1]]++}END{for (i in ip) print i,ip[i]}'

        length(string)
            功能:返回给定字串的长度

        substr(string,start[,length])
            功能:从string中取子串,从start为起始位置为取length长度的子串;

四)数组

   1、bash shell只支持一维数组,但参数个数没有限制。
     声明一个数组:
      declare -a array
   (其实不用声明,按数组方式直接赋值给变量即可,BASH就知道那是数组)
     数组赋值:
     (1) array=(var1 var2 var3 ... varN)
     (2) array=([0]=var1 [1]=var2 [2]=var3 ... [n]=varN)
     (3) array[0]=var1
     arrya[1]=var2
     ...
     array[n]=varN
    计算数组元素个数:
    ${#array[@]}  或者  ${#array[*]}
    BASH的特殊参数 @ 和 * 都表示“扩展位置参数,从1开始”,但形式稍有差异,但在数组里使用好像是可以通用的。
    引用数组:

    代码如下:

    echo ${array[n]}

    遍历数组:

    代码如下:

    filename=(`ls`)
    for var in ${filename[@]};do
    echo $var
    done

2. AWK 数组

  定义:

  在 awk 中,数组是关联数组,它的特点是:

  数组的下标可以是整数,也可以是负数甚至是字符串

  数组的下标可以不连续。

  Awk 的变量 IGNORECASE 的值不影响数组下标。

  当 awk 创建一个数组的时候,如果没有指定下标,默认已连续整数作为下标,起始值是 1.

  Awk 的数组是什么高效的,访问一个元素的时间跟元素的数量无关。

  注: awk 的下标其实都是字符串,如我们输入的是数字 1 , awk 会自动的转换为字符串“ 1 ”。

     引用 awk 元素的基本方法是:

     ARRAY[INDEX]

     注: 在此引用方式中除非 [ ] 中写的是变量,否则需要添加双引号,即字符串必需添加双引号的规则在数组的下标中也必需遵守,但如果下标是全数字,则可以不加引号,例:

     Bb=“123”

     arr[bb] awk 将 bb 认作变量,获取的是 arr[“123”] 的值

     arr[234] awk 将 234 认作字符串,虽然 234 没加引号。因为变量的定义不能用全数字,所以 234 肯定是字符串,而不是变量。

     arr[“ bb” ] awk 将 bb 认作字符串,获取的是 arr[“bb”] 的值

有时候,数组的 value 会为空。 value 为空的元素包含两种情况:

      1 、本身 value 为空;

      2 、通过 delete 删除后的元素。这两种情况都可以被正常引用。但不幸的是,如果引用了一个不存在的元素,会导致 awk 创建这个元素, value 为空,这样,会导致 awk 的内存浪费。

      如果要查询具有某个 index 值的元素是否存在可以用如下的表达式:

      INDEX in ARRAY

      这个表达式仅仅测试具有 INDEX 的元素在 ARRAY 中是否存在。如果不存在,该表达式不会导致产生以 INDEX 为下标的 value 为空的元素。

     如果元素存在,该表达式返回值 1 ( true )

     反之,返回 0 ( false )

     例:测试在数组 frequencies 中是否存在下标为 2 的元素

      if (2 in frequencies)

      print “Sub 2 is present.”

      注: 不能测试 frequencies 中是否存在 value 为 2 的元素,除非scan 数组中的所有元素。

       给元素赋值 :

      给 awk 的数组赋值,只能采用如下形式:

      ARRAY[SUB] = VALUE

      ARRAY :数组名字

      SUB :下标

      VALUE :值

      注: awk 可以生成下标为空的元素,但是引用方式必需是 arr[ “” ], 而不是 arr[]。

      length(a) 求得数组中元素的个数。

     遍历数组:

   在使用数组的程序里,经常会使用一个循环让数组里的每一个元素都执行一次某一个操作。在其他程序里,数组的下标是连续的正整数,因此所有的下标很容易通过从低到高实现遍历。但这个方法在 awk 里不能使用,因为 awk 的下标可以是数字也可以是字符串。因此, awk 使用一种特别的语句来遍历数组里的元素:

      for (VAR in ARRAY)

      BODY

      以上的循环将实现让数组 ARRAY 里的每一个元素都执行一次 BODY 。

以下程序的第一部分,将输入文本的每一个单词都作为下标存放入数组,如单词有重复,仅仅保留一个,因数组的下标是不能重复的。

      删除元素:

      删除单个元素

      delete ARRAY[INDEX]

      删除整个数组方法 1

      for (VAR in ARRAY)

      delete ARRAY[VAR]

      删除整个数组方法 2 (该方法 gawk 专用,可移植性差,但效率是方法 1 的 3 倍左右)

      delete ARRAY

Awk 的数组和变量用的是同一个地址空间,数组的名字和变量不能重名。

      数组赋值:

      单个赋值: Tarray[1]="cheng mo"  Tarray[2]="800927"

      多个赋值:awk 'BEGIN{info="it is a test"; lens=split(info,tA," "); print length(tA), lens, tA[1];}'

八 命令及语法格式

  一)bash shell脚本

        文本文件
        运行脚本:事实上是运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,而后由bash进程负责解析并运行此逻辑;
        启动脚本:
            (1) # bash /PATH/TO/SCRIPT_FILE
            (2) 一个执行权限,
                # ./PATH/TO/SCRIPT_FILE

                shebang:
                    #!/bin/bash

        第一行:顶格给出shebang
        注释行:#

        bash的常用选项:
            -n: 检查脚本中的语法错误;
            -x:调试执行脚本;

    命令状态结果:
        bash进程用于追踪执行的命令成功与否的状态:
            0: 成功
            1-255:失败

        特殊变量:
            $?:上一条命令的执行状态结果;

        布尔型:
            “真”:成功
            “假”:失败

        自定义脚本的状态结果:
            exit [n]

            注意:脚本中任何位置执行了exit命令即会终止当前shell进程;

   二)  sed

         sed命令:

         基本正则表达式元字符:
         字符匹配:., [], [^]
         次数匹配:*, \?, \+, \{m,n\}, \{n\}
         位置锚定:^, $, \<, \>
         分组及引用:\(\), \1, \2, ...
         多选一:a|b|c

         vim编辑中文本的查找替换:
         地址定界s/要查找的内容/替换为的内容/
         要查找的内容:可使用正则表达式
         替换为的内容:不支持正则表达式,但支持引用前面正则表达式分组中的内容
         地址定界:%, startline,endline

    语法:sed [OPTION]... {script} [input-file]...

        工作机制:每次读取一行文本至“模式空间(pattern space)”中,在模式空间中完成处理;将处理结果输出至标准输出设备;

        -r: 支持扩展正则表达式;
        -n: 静默模式;
        -e script1 -e script2 -e script3:指定多脚本运行;
        -f /path/to/script_file:从指定的文件中读取脚本并运行;
        -i: 直接修改源文件;

        地址定界:
            #: 指定行;
            $: 最后一行;
            /regexp/:任何能够被regexp所匹配到的行;
            \%regexp%:同上,只不过换作%为regexp边界符;
            /regexp/| :
            \%regexp%| :匹配时忽略字符大小写;
            startline,endline:
          #,/regexp/:从#行开始,到第一次被/regexp/所匹配到的行结束,中间的所有行;
                #,#
            /regexp1/,/regexp2/:从第一次被/regexp1/匹配到的行开始,到第一次被/regexp2/匹配到的行结束,中间的所有行;
          #,+n:从#行开始,一直到向下的n行;
          first~step:指定起始行,以及步长;
                1~2,2~2

        sed的编辑命令
            d: 删除模式空间中的行;
            =:显示行号;
            a \text:附加text
            i \text:插入text,支持\n实现多行插入;
            c \text:用text替换匹配到的行;
            p: 打印模式空间中的行;
            s/regexp/replacement/:替换由regexp所匹配到的内容为replacement;
            g: 全局替换;
               
            w /path/to/somefile:把指定的内容另存至/path/to/somefile路径所指定的文件中;
            r /path/from/somefile:在文件的指定位置插入另一个文件的所有内容,完成文件合并;

            sed命令另一个称作"hold space"的内存空间:

            高级命令:
                h:用模式空间中的内容覆盖保持空间的内容;
                H:把模式空间中的内容追加至保持空间中内容的后面;
                g:从保持空间中取到其内容,并将其覆盖模式空间中的内容;
                G:从保持空间中取到其内容,并将其追加在模式空间中的内容的后面;
                x:把保持空间和模式空间中的进行交换;
                n:读取匹配到的行的下一行至模式空间;(会覆盖模式空间中的原有内容);
                N:读取匹配到的行的下一行至模式空间,追加在模式空间中原有内容的后面;
                d:删除模式空间中的内容;
                D:删除多行模式空间中的首行;

                注意:命令功能可使用!取反;分号可用于分隔脚本;

三)AWk

    1.基本语法
    awk [options] 'program' file file ...
    awk [options] 'PATTERN{action}' file file ...

    -F CHAR:输入分隔符

    2、awk的输出

    print item1, item2,...
    要点:
    (1) 各项目之间使用逗号分隔,而输出时则使用输出分隔符分隔;
    (2) 输出的各item可以字符串或数值、当前记录的字段、变量或awk的表达式;数值会被隐式转换为字符串后输出;
    (3) print后面item如果省略,相当于print $0;输出空白,使用pirnt "";

     3.printf命令

        命令的使用格式:printf format, item1, item2,...

        要点:
        (1) 要指定format;
       (2) 不会自动换行;如需换行则需要给出\n
        (3) format用于为后面的每个item指定其输出格式;

        format格式的指示符都%开头,后跟一个字符:
            %c: 显示字符的ASCII码;
            %d, %i: 十进制整数;
            %e, %E: 科学计数法显示数值;
            %f: 显示浮点数;
            %g, %G: 以科学计数法格式或浮点数格式显示数值;
            %s: 显示字符串;
            %u: 显示无符号整数;
            %%: 显示%自身;

        修饰符:
            #:显示宽度
            -:左对齐
            +:显示数值的符号
            .#: 取值精度

       4、模式:

        (1) Regexp: 格式为/PATTERN/
            仅处理被/PATTERN/匹配到的行;
        (2) Expression: 表达式,其结果为非0或非空字符串时满足条件;
            仅处理满足条件的行;
        (3) Ranges: 行范围,此前地址定界,
            NR
            仅处理范围内的行
        (4) BEGIN/END: 特殊模式,仅在awk命令的program运行之前(BEGIN)或运行之后(END)执行一次;
        (5) Empty:空模式,匹配任意行;

       5、常用的action:

        (1) Expressions
        (2) Control statements
        (3) Compound statements
        (4) input statements
        (5) output statements

九、练习

      一)写一个脚本:如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;

     解:vim file.sh

    #!/bin/bash
    # 
    file1="/tmp/test"
   if [ -e $file1 ];then
    echo  "$file1 exists."
    file  $file1
    exit 3
    else
    mkdir -p $file1
    fi image

  二)写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:脚本参数,命令交互.

   解:vim num1.sh

#!\bin\bash
#
echo "you input  integers they are: " read $1 $2
if [ $# -lt 2 ]; then
     echo "need input two integers,please tryagin"
     exit 5
elif [ $1  -gt  $2 ]; then
  echo "Max:$1,Min:$2."
else
  echo "Max:$2,Min:$1."
fiimage

三) 求100以内所有奇数之和.至少用3种方法。
#!/bin/bash
#
declare -i sum=0
for i in $( seq 1   2  100); do
    sum=$(( $i+$sum))
done
echo "100 以内的奇数之和为:$sum"

#!/bin/bash
#
declare -i sum=0
declare -i i=1
while [ $i -le 100 ]  ; do
     let sum+=$i
     let i+=2

done
echo " even sum is : $sum"
#!/bin/bash
#
declare -i sum=0
declare -i i=1
until [ $i -gt 100 ]  ; do
     let sum+=$i
     let i+=2

done
echo " even sum is : $sum"

image

四)写一个脚本实现如下功能:

(1) 传递两个文本文件路径给脚本;

(2) 显示两个文件中空白行数较多的文件及其空白行的个数;

(3) 显示两个文件中总行数较多的文件及其总行数

  解:

#!/bin/bash
#
if [ $# -le 1 ]; then
echo "条件不足,请最少输入2个文件路径"
exit 4
fi
file1=$( grep -E "^$" $1 | wc -l )
echo " null line $file1"
file2=$( grep -E "^$" $2 | wc -l)
file3=$(  wc -l "$1" | cut -d '/' -f 1 )
echo "$file3"
file4=$( wc -l "$2" | cut -d '/' -f 1 )
echo "$file4"
echo " null line $file2"
if  [ "$file1" -gt "$file2" ]; then
   echo " max null line file is $1,null line num is $file1"
fi
if [ "$file1" -lt "$file2" ]; then
    echo " max null line file is $2,null line is $file2"
fi
if [ "$file3" -gt "$file4" ]; then
   echo "max total line file is $1, total line is $file3"
fi
if [ "$file3" -lt "$file4" ]; then
   echo "max total line file is $2, total line is $file4"
fi

image

五)写一个脚本

(1) 提示用户输入一个字符串;

(2) 判断:

如果输入的是quit,则退出脚本;

否则,则显示其输入的字符串内容;

解:

#!/bin/bash
#
read -p "请输入任意字符:" -t 10 str1
if [ "$str1" == 'quit' ]; then
  echo "您输入的是退出指令。"
else
  echo "您刚才输入的字符串是:$str1"
fi

image

六)写一个脚本,打印2^n表;n等于一个用户输入的值;

解:

#!/bin/bash
#
declare -i num4
declare -i i
read -p "请输入任意一个整数:" -t 5 num4
for i in $( seq 0 1 $num4 ) ;do
   let y=$[ 2**i]
   echo " 2^$i=$y"
done

image
七)写一个脚本,写这么几个函数:函数1、实现给定的两个数值的之和;函数2、取给定两个数值的最大公约数;函数3、取给定两个数值的最小公倍数;关于函数的选定、两个数值的大小都将通过交互式输入来提供。

解:

#!/bin/bash
#
#declare -i num1
#declare -i num2
read -p " 请输入函数和两个整数:" -t 10  fun num1 num2
if [ -z "$fun" ] ; then
echo " 您没有按要求输入函数"
exit 5
fi
if [  -z "$num1" ]  ; then
echo "您没有按要求输入整数"
fi
if [ -z "$num2" ]  ; then
echo "您没有按要求输入整数"
fi

sum () {
if [ "$fun" == 'sum' ]; then
   sum=$[ $num1+$num2 ]
  echo "您输入的$num1+$num2=$sum"
fi
}

gcd () {
   if [ "$fun" == 'gcd' ]; then 
     declare -i tmp
     declare -i num3=$num1
     declare -i num4=$num2
     while [ "$num4" -ne  0 ]; do
       tmp=$[ $num3% $num4 ]
      num3=$num4
      num4=$tmp
     done
     echo " gcd is $num3"
fi
}

lcm () {
    if [ "$fun" == 'lcm' ]; then
    declare -i tmp
     declare -i num3=$num1
     declare -i num4=$num2
     while [ "$num4" -ne  0 ]; do
       tmp=$[ $num3% $num4 ]
      num3=$num4
      num4=$tmp
     done
     tmp1=$[ $[ $num1/ $num3 ]* $[$num2/ $num3 ]* $num3 ]
    echo " $num1 and $num2 lcm is $tmp1"
fi
}
 
    case $fun in
     sum)
       sum
       ;;
     gcd)
       gcd
       ;;
     lcm)
       lcm
       ;;
    *)
        echo " you are input function don't include"
        exit 6
   esac

image