Linux之linux bash scripts


     进程是程序运行时的内存空间和设置,存在于用户空间;用户空间是存放运行的程序和它们的数据的一部分内存空间。shell是用户和Linux内核之间的接口程序,围绕内核的外层。当从shell或其他程序向Linux传递命令时,内核会做出相应的反应。shell也是一个解释型的程序设计语言,支持绝大多数在高级语言中能见到的程序元素,如数据变量、参数传递、判断、流程控制、数据输入和输出,子程序及以中断处理等。

      shell程序的编译过程分为预处理、编译、汇编、链接等几个阶段

      大致的执行过程,图示:

wKiom1X-xe6QbA5lAAB3v15Itko379.jpg

          1、执行指令,等待用户输入命令

          2、将字符逐一读到寄存器中

          3、再从寄存器取出放到主存中

          4、键入命令结束后提交,代码和数据被拷贝到主存

          5、执行主程序中的机器语言指令,并且从主存拷贝到寄存器堆

          6、从寄存器中把执行过后的指令传到或者拷贝到显示设备

      关于shell环境配置以及变量命名、作用、销毁等,已经在http://daisywei.blog.51cto.com/7837970/1690785博文做了简要的讲解。这里重点强调特殊变量

     $0:当前脚本的文件名

     $n:传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2

     $#:传递给脚本或函数的参数个数

     $*:传递给脚本或函数的所有参数

     $@:传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到

     $?:上个命令的退出状态,或函数的返回值

     $$:当前Shell进程ID

     程序基本格式:

     行开始(必须方在文件的第一行):

     #!/bin/bash        符号#!用来告诉系统它后面的参数是用来执行该文件的程序,被称为shebang。例子中我们使用/bin/bash来执行程序。当编辑好程序需要有执行权限(chmod +x filename)。

     注:进行shell编程时,以#开头的句子表示注释,直到这一行的结束

     bash脚本一般指文本文件。运行bash脚本指运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,而后由bash进程负责解析并运行此逻辑

     执行脚本命令有(注意要赋予执行脚本的文件有x执行权限):

         1、 # bash /PATH/TO/SCRIPT_FILE

2、# ./PATH/TO/SCRIPT_FILE 

     bash命令常见选项:

        bash -n bashname(脚本文件名) 检查bash脚本的语法错误

        bash  basename(脚本文件名)  执行脚本

        bash  -x  bashname   显示脚本执行的详细过程


    练习:

    1、编辑test.sh并检查语法,显示详细的执行脚本过程(需要应用各个特殊参数表达的不同含义)

wKioL1X-yEyBUxWWAADlr4UyWgs911.jpgwKiom1X-xhjhaGvHAAJjxvYmncs390.jpg       一般bash命令的执行状态结果,由bash追踪和保存,有:结果的返回值,状态返回值。

       使用特殊变量$? :保存最近一条命令的状态结果

       布尔型:真或假

       bash命令状态返回值:成功:0;失败:1-255,(其中1、2、127被系统保留)

       自定义脚本的状态结果:exit [n] (注:n必须是十进制数,范围必须是0-255,脚本中任何位置执行了exit命令即会终止当前shell进程)

 

    练习:

    1、查看执行状态

wKioL1X-yGmAImYbAAGpCGnC6ug761.jpg

    2、编辑test1.sh,打印执行返回状态

wKioL1X-yHey8SkgAADPtpBjCEk474.jpgwKiom1X-xkKiKJW-AAC0hXXut-s310.jpg

     变量类型其他编程语言有多种类型,如C中定义变量需要声明整型、浮点型、字符型等。而shell脚本变量却是无类型的。shell不支持浮点型只支持整型(数值型)和字符型,同时字符型还具有一个整型值0(判断标准:变量中只包含数字是数值型其他是字符串)。

     变量类型声明定义

         declare –a name :表明数组array

         declare –f name :表明函数function

         declare –i name :定义整型变量

         declare –r name :表示只读。不能使用unset         

         declare –x name :同export,在当前的环境中起作用,也在外部的shell环境中起作用,本地变量


     test命令检查最后所执行命令的状态。test测试一个表达式,然后返回真或假。表达式一般是文本、数字或文件和目录属性的比较,并且可以包含变量、常量和运算符(字符串运算符、整数运算符、文件运算符或布尔运算符)

      语法:test expression

            [ expression ]

            ` EXPRESSION `

    整数变量、字符串变量算术比较:

     对应操作 整数操作 字符串操作

       相等           -eq              =

       不等           -ne             !=

       大于           -gt              >

       小于           -lt              <

    大于或等于   -ge

    小于或等于   -le

       为空                       -z

      不为空               -n


   判断文件属性的操作符:

       -e file:判断文件是否存在,并返回真或假

       -f file:文件是否存在且为普通文件

       -s file:文件是否存在且大小不为0

       -d file:文件是否存在且为一个目录

       -h file:是否存在且为符号链接文件

       -b file:是否存在且为块设备文件

       -c file:是否存在且为字符设备文件

       -S file:是否存在且为套接字文件

       -p file: 是否存在且为管道文件


       -r file:判断当前文件对当前用户可读

       -w file:判断当前文件对当前用户可写

       -x file:判断当前文件对当前用户可执行

       -g file:判断当前文件对当前有SGID权限

       -u file:判断当前文件对当前有SUID权限

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

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


     双目操作符:

         file1 -nt file2 文件1比文件2更新  (注意:这里指file1与file2最近一次的修改时间戳)

         file1 -ot file2 文件1比文件2更老   (注意:这里指file1与file2最近一次的修改时间戳)


      特殊设备:

 /dev/null: 空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据

 /dev/zero:一个特殊的文件,读取它时,会提供无限的空字符(NULL, ASCII NUL, 0x00)


      逻辑判断:

      !:非,对指定的条件取反

     -a:与,多个条件要同时满足

     -o:或,多个条件满足其一即可

     ||:用or来合并两个条件(也称短路操作符)

     &&:用and来合并两个条件(也称短路操作符)

     短路操作符,逻辑判断真与假

      false && true = false

false && false = false

         true && false = fase

         true && true = true

true || true = true

true || false = true

          false || true = true

          false || false = false

     练习:

     1、通过运行脚本test2.sh、test3.sh,对两个数值的比较 

wKiom1X-xlSDW3CtAADXNgsRLt0933.jpgwKioL1X-yJqABMi9AABHFDWBZxU291.jpgwKioL1X-yKvyh-a6AADKeXfhI9s269.jpgwKiom1X-xnfxS66LAABwhKM9mVM156.jpg

     2、通过运行脚本test4.sh,对两个字符串的比较

wKiom1X-xoPh84XkAACypIALNT8666.jpgwKioL1X-yMih_6bYAABU95Wi330060.jpg

     3、判断目录$test是否存在,不存在,则创建

wKiom1X-xqbT8MprAAD_kTaT-X8777.jpgwKioL1X-yOzAWt3SAAOpK92uCSo209.jpg

     4、判断普通文件$test是否存在,不存在,则新建

wKiom1X-xsHAVopVAADtRtbkEuw529.jpgwKioL1X-yQbg4EncAACd8fqAK_w412.jpg

     5、判断$test是否存在并且具有执行权限,没有执行权限,并赋予执行权限

wKiom1X-xtqA6T-OAAG-qmofhYY979.jpg

     6、写一个脚本实现如下功能:获取当前主机的主机名;如果当前主机的主机名为空,或者为localhost,则将其修改为10.com

wKioL1X-ySbyQPxEAAFKl4uDxrc423.jpg

     7、自动清空日志文件的内容(使用双目操作并且重定向、特殊设备)

 wKiom1X-xvngUsw8AAEYthpHB0k335.jpg

    read命令:从标准输入中读取一行

    语法:read [ -p ][  -r ][ -s ][ -u[ n ] ] [  VariableName?Prompt ] [ VariableName ] ... 

    -p "内容":屏幕就会输出提示语句

    -t  时间 :等待时间

    练习:

    1、输出提示语“enter your name:”,并且显示名字

wKioL1X-yUrw0H4aAAD0VOMaI-Y216.jpg

    命令引用,将直接引用执行结果:

        `命令`:被反引号

       $(命令)

    注意:$[ 算术运算式 ]的形式进行求值,[]必须有空格分隔,只支持整型运算(常用的算术运算符+, -, *, /, %, **等)

          $((运算式))的形式也可以进行算术运算求值,并且可以进行布尔运算

          let 运算式也能进行算术运算,算术式各元素间不得有空格,否则应将算术式用引号括起来

     练习:

     1、显示当前时间(用两种方法引用)

wKiom1X-xxrj8Px-AACpa6QKVhA984.jpg

     2、计算5和6的和

wKiom1X-xyixjdBcAABOWmPDz00415.jpg


     bash之流程控制if/else(条件判断)、case语句

     格式:单分支、双分支、多分支

     if [ 条件判断式 ]; then

语句块                  //当条件判断式为真时,执行该语句块

     fi   

      

     if [ 条件判断式 ]; then

语句块                  //当条件判断式为真时,执行该语句块

     else

        语句块                  //当条件判断式为假时,执行该语句块

     fi   

     case语句:重分支的应用场景,类似if语句多分支

       格式如下:

            case 变量名 in

                模式1)

            命令序列1

            ;;

                模式2)

            命令序列2

         ;; 

                *)

            默认执行的命令序列

            esac 

注:case行尾必须为单词“in”,每一个模式必须以右括号“)”结束;双分号“;;”表示命令序列结束;匹配模式中可是使用方括号表示一个连续的范围,如[0-9];使用竖杠符号“|”表


示或;最后的“*)”表示默认模式,当使用前面的各种模式均无法匹配该变量时,将执行“*)”后的命令序列

     练习:

     1、写一个脚本if01.sh,判断当前文件系统为Linux,如果是则显示

wKiom1X-xzbC0rqLAAD8TXOMZOE956.jpg

     2、写一个脚本if02.sh,判断当前系统为Linux或者FreeBSD、Solaris,如果以上都不是则显示是什么操作系统

wKioL1X-yX3Q_JhOAAHQkWujFdw556.jpg

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

wKioL1X-yYqDI_biAAL_XrWL74k827.jpg

     4、写一个脚本case01.sh,由用户从键盘输入一个字符,并判断该字符是否为字母、数字或者其他字符,并输出相应的提示信息。

wKiom1X-x1_DfpY9AAIJz4i76q0413.jpg

     5、写一个脚本if04.sh可接受四个参数start: 创建文件/var/lock/subsys/SCRIPT_NAME、stop: 删除此文件、restart: 删除此文件并重新创建、status: 如果文件存在,显示为"running",否则,显示为"stopped"、basename命令:取得路径的基名 (使用case语句)

#!/bin/bash
#
prog=$(basename $0)                                                                 #获取路径的基名
lockfile="/var/lock/subsys/$prog"                                                   #定义lockfile变量并赋值
if [ $# -lt 1 ]; then                                                               #判断传递参数个数($#)小于1则显示下面echo内容,并退出
   echo "Usage: $prog start|stop|restart|status"
    exit 1
fi
case $1 in                                                                          #判断第一个参数
start)                                                                              #如果第一个参数为start则继续执行下面语句
if [ -f $lockfile ]; then                                                           #判断文件是否存在,存在则显示下面echo内容
    echo "$prog is started yet."
  else                                                                              
touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."   #如果不是start参数则创建文件,并且显示文件内容,||注意这里的短路操作符
fi                                                                
;;
stop)                                                                               #判断为stop则继续执行下面语句
if [ -f $lockfile ]; then                                                         
rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."          
 else
echo "$prog is stopped yet."
fi
;;
restart)                                                                            #判断为restart
  if [ -f $lockfile ]; then
rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."
else
touch $lockfile && echo "$prog is stopped, Starting $prog ok...."
fi
;;
status)                                                                             #判断为status
if [ -f $lockfile ]; then
echo "Running..."
else
echo "Stopped..."
fi
;;
*)
 echo "Usage: $prog start|stop|restart|sttus"                                       #如果用户输入的都不是以上的字符,则给出提示输入相关可使用的字符
 exit 1
esac

wKioL1X-ybPR8qSXAADVIvTqoR0316.jpg

      bash之流程控制for、while、until(循环)

      循环命令用于特定条件下决定某些语句重复执行的控制方式,有三种常用的循环语句:for、while和until。while循环和for循环属于“当型循环”,而until属于“直到型循环”。循环控制符:break和continue控制流程转向。

      for循环:列表for循环(列表非空开始进入循环体,遍历列表循环结束),不带列表for循环

      格式:

      for 变量 in 列表[list];do    ---列表list:是由一个或多个空格或换行符分隔开的字符串组成;把列表的每个字符串逐个赋值给变量

      语句块

      done


      for 变量 ;do    

      语句块

      done

      列表list获得方法:

      1、整数列表{start..end}  $(seq [start `step` end)

      2、直接给出列表

      3、globbing

      4、命令生成

      练习:

      1)、遍历ab、ac、ad列表,并输出

wKiom1X-x5uQA3tjAACGp4MYV-c489.jpg

      2)、编写脚本for01.sh,创建10个用户,如果用户已存在则不用创建(练习整数列表)

wKiom1X-x7rCLypCAAIBHG7kt1k980.jpg  

      3)、编写脚本for02.sh,遍历/var/log/目录下所有文件(练习globbing)

wKiom1X-x8nBX0FXAAMQDp2I4pg296.jpg

      4)、编写脚本for03.sh,列出所有用户的属组(练习命令引用生成列表)

wKioL1X-yhaRkhgMAAIozoDUku4121.jpg

      5)、编写脚本for04.sh,算术运算,求100以内所以正整数之和;

wKioL1X-yiTTI_-sAAF_8l7o5KU067.jpg

     6)、编写脚本for05-01.sh、for05-02.sh、for05-03.sh,算术运算,求100以内所有偶数之和;使用至少三种方法实现;

wKiom1X-yAeh5pUjAAFh_EPaRW0210.jpgwKiom1X-yBDxRufKAAFhpNlBVi8554.jpgwKioL1X-ylWyIsLuAAFLsejM_W0338.jpg

      注意:增强型赋值算术运算:+=、-=、 *=、/=、 %=,如:sum=$[$sum+$i]等同于let sum+=$i

     7)、编写脚本for05.sh,显示/etc目录下所有普通文件列表,而后统计一共有多少个文件;    

wKioL1X-ym6h5ZpMAAKU1T9goHg116.jpgwKioL1X-ynmSpREJAAEYZHxnQ-E541.jpg

     8)、编写脚本for06.sh,写一个脚本,打印九九乘法表(练习循环嵌套)

wKiom1X-yE2SbZLfAAH_lqIsZP4783.jpg

          for循环的特殊用法:

 格式:for ((expr1;expr2;expr3)); do   #expr1: 定义控制变量,并初始赋值;expr2: 循环控制条件;expr3: 修正控制变量

循环体

done

         while循环

         格式:expression条件为真进入循环体,expression为假退出循环

         while expression;do     

            循环体

         done


      练习:

      1)、编写脚本for07.sh,求100以内所有正整数之和(使用while循环)

wKioL1X-ypqhGhx3AAEnZAN12mk118.jpg

      2)、编写脚本for08.sh,打印九九乘法表

wKiom1X-yGrzVxT_AAJ-ch2mGXA471.jpg

while循环的特殊用法:遍历文件的每一行

格式:while read VARIABLE; do

 循环体

         done < /PATH/FROM/SOME_FILE    #/PATH/FROM/SOME_FILE文件路径


      练习:

      1)、编写脚本for09.sh,找出UID为偶数的所有用户,显示其用户名和ID号;

wKiom1X-yHqBCAU7AAG45H2Mx6g610.jpg

               

       until循环:直到型循环

       格式:expression条件为假进入循环体,expression为真退出循环,与for、while进入循环体的条件相反

         until expression;do     

         循环体

         done

       练习:

      1)、编写脚本until01.sh,求100以内所有正整数之和(使用until循环)

wKioL1X-ysnhUwKBAAFJZxBaQT0147.jpg

        

       流程控制:continue、break

       continue 语句用来跳过本次循环中的代码,直接跳回到循环的开始位置。如果条件为真则开始下一次循环,否则退出循环

       break 语句可以结束while,for,until等结构的执行,即从结构中跳出。退出循环后,转到done语句后继续执行

       格式:

          while CONDITION; do

循环体

if CONDITION2; then

break [n]

fi

  done


  while CONDITION; do

循环体

if CONDITION2; then

continue [n]

fi

循环体

done

        练习:

        1)、编写脚本continue01.sh,求100以内所有齐数之和;

wKioL1X-yt_wP91SAAHQizsDcWo520.jpg


          特殊循环:死循环

          格式:

            while true; do    ---永远为真

循环体

if CONDTION; then

break

fi

    done


    until false; do   ---永远为假

循环体

if CONDITION; then

break

fi

done

           

练习:

        1)、编写脚本break01.sh,脚本进入死循环直至用户输入数字大于3。要跳出这个循环,返回到shell提示符下

wKiom1X-yLqzXPWEAAJ0ZEFvs0Y467.jpg

        2)、编写脚本break02.sh,每隔3秒钟查看当前系统上是否有名为“gentoo”的用户登录;如果某次查看gentoo登录了,则显示gentoo已经登录;如果未登录,就显示仍然未来,并显示这是已经是第多少次查看了;

wKioL1X-ywrS3X81AAHnOwBQ744386.jpg


     bash shell用户可定义函数,然后在脚本中可以随便调用。函数最大作用就是让程序模块化,即把脚本文件中的代码分隔为多段,放在不同的文件中。

     函数作用域:函数仅在定义的shell环境中有效,如果要传递函数给子shell环境使用,需要使用命令export及其选项-;同时函数中的变量默认是全局的。可用local将变量设置为函数私


有的。

     语法:

     [ function ] funname [()]


                 {

                   action;


                   [return int;]


                   }


      1、可用function fun()  定义,也可直接fun() 定义,不带任何参数。

      2、参数返回加:return;如不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)


      练习:

      1)、改造if04.sh脚本为fun01.sh,已函数来定义

#!/bin/bash
#
prog=$(basename $0)
lockfile="/var/lock/subsys/$prog"
#echo $lockfile
if [ $# -lt 1 ]; then
    echo "Usage: $prog start|stop|restart|status"
    exit 1
fi
start() {                                                                              #注意这里已函数来定义
    if [ -f $lockfile ]; then
echo "$prog is started yet."
    else
touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."
   fi
}
stop() {
    if [ -f $lockfile ]; then
rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."
    else
echo "$prog is stopped yet."
    fi
}
restart() {
    if [ -f $lockfile ]; then
rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."
    else
touch $lockfile && echo "$prog is stopped, Starting $prog ok...."
    fi
}
status() {
    if [ -f $lockfile ]; then
echo "Running..."
    else
echo "Stopped..."
    fi
}
case $1 in
start)
    start 
    ;;
stop)
    stop
    ;;
restart)
    restart
    ;;
status)
    status
    ;;
*)
 echo "Usage: $prog start|stop|restart|sttus"
    exit 1
esac


     2)、编写脚本fun02.sh,判断用户的ID号的奇或者偶数;

wKiom1X-yN_CEXY6AAHPUqdLvm8628.jpg


汇总练习:

1、写一个脚本:如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;(不要怀疑,就是这么简单)

wKioL1X-yzKTt7RuAAGwv9k65RY931.jpg

2、写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:脚本参数,命令交互;(使用read,依然如此简单)

wKiom1X-yQaxmFBIAAL_XrWL74k115.jpg

3、求100以内所有奇数之和(至少用3种方法。是的这是我们的作业^_^)

wKiom1X-yRiit7xTAAGu30C70fk862.jpgwKioL1X-y13Sc9npAAChthEtVyM150.jpg

4、写一个脚本实现如下功能:

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

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

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

wKioL1X-y2yRU5q0AAMLrvmmqIw405.jpg

5、写一个脚本:提示用户输入一个字符串;判断:如果输入的是quit,则退出脚本;否则,则显示其输入的字符串内容;

wKiom1X-yT3ioVmbAAFHOyVSPwg818.jpg

6、写一个脚本:打印2^n表;n等于一个用户输入的值;(不好意思,我调皮了)

wKiom1X-yUyRJDRJAAGeid8UcYI614.jpg

7、写一个脚本,写这么几个函数:函数1、实现给定的两个数值的之和;函数2、取给定两个数值的最大公约数;函数3、取给定两个数值的最小公倍数;关于函数的选定、两个数值都将通过脚本参数进行输入。

wKiom1X-yVmC-r9VAAIS2f661rQ823.jpgwKioL1X-y6HQDddGAAC_LVl8SXc248.jpg

       bash shell之sed工具

       sed工具:一种流编辑器,又称行编辑器,它一次处理一行内容。

      工作原理:把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

      定址:定址来定位所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围(包括行数表示的那两行),0个行数指没有定址,处理文件的所有行。


如1,3表示1,2,3行,美元符号($)表示最后一行。

      常用的语法格式:

     (1)Sed [options] ‘script’ input_file…

     (2)Sed [options] –f script_file input_file…

     (3)Sed [options] ‘ADDR1,ADDR2command’ input_file…

      常用选项:

       -n:关闭默认输出,默认将自动打印所有行

       -e script1 -e script2 -e script3:多点编辑,允许多个脚本指令被执行

       -r:支持扩展正则

       -i:可以修改原文件,慎用!

       -f:支持使用脚本


       定界符

          #: 指定行;

 $: 最后一行;

   /regexp/:任何能够被regexp所匹配到的行;

  \%regexp%:同上,只不过换作%为regexp边界符;

  \%regexp%| :匹配时忽略字符大小写;

  startline,endline:开始行,结束行

         #,/regexp/:从#行开始,到第一次被/regexp/所匹配到的行结束,中间的所有行

/regexp1/,/regexp2/:从第一次被/regexp1/匹配到的行开始,到第一次被/regexp2/匹配到的行结束,中间的所有行

      #,+n:从#行开始,一直到向下的n行

first~step:指定起始行,以及步进,如:1~2,2~2


        常用命令选项

           a\:在当前行下面插入文本 

           i\:在当前行上面插入文本

           c\:把选定的行改为新的文本 

            d:删除,删除选择的行

            s:替换指定字符 

            p:打印模板块的行

            r:file 从file中读行 

            w:file 写并追加模板块到file末尾 

            =:打印当前行号码


        常用替换标记

            g:表示行内全面替换

            \1:子串匹配标记 

            &:已匹配字符串标记


        常用元字符   

           ^:匹配行开始,如:/^abc/匹配所有以abc开头的行 

           $:匹配行结束,如:/abc$/匹配所有以abc结尾的行 

           .:匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d

           *:匹配0个或多个字符,如:/*abc/匹配所有模板是一个或多个空格后紧跟sed的行 

          []:匹配一个指定范围内的字符,如/[aa]bc/匹配abc和Abc 

         [^]:匹配一个不在指定范围内的字符,如:/[^A-RT-Z]bc/匹配不包含A-R和T-Z的一个字母开头,紧跟bc的行 

      \(..\):匹配子串,保存匹配的字符,如s/\(test\)able/\1rs,testable被替换成testlrs。 

           &:保存搜索字符用来替换其他字符,如s/test/**&**/,test这成**test**。 

          \<:匹配单词的开始,如:/\ 匹配单词的结束,如/test\>/匹配包含以test结尾的单词的行

      x\{m\}:重复字符x,m次,如:/0\{5\}/匹配包含5个0的行 

     x\{m,\}:重复字符x,至少m次,如:/0\{5,\}/匹配至少有5个0的行 

    x\{m,n\}:重复字符x,至少m次,不多于n次,如:/0\{5,10\}/匹配5~10个0的行


    练习:

        1、把/tmp/test.txt下aaa替换成AAA,并且打印显示该行

wKioL1X-zBGymvQ7AAESkIzFv88399.jpg

        2、删除/tmp/test.txt下空白行(注意元字符的应用)

wKiom1X-yfbwgJdEAADnk3RkU8w073.jpg

        3、删除/tmp/test.txt下空格开头的行

wKioL1X-zD6RGCcYAADhJAJymJw039.jpg

4、删除/tmp/grub.cfg文件中所有行的行首的空白字符

wKiom1X-yguRglqgAAJwHvIkSnc575.jpg

5、删除/tmp/fstab文件中所有以#开头,后跟至少一个空白字符的行的行首的#和空白字符

wKioL1X-zFPB6MKOAARATwL2A2E197.jpg

6、把/tmp/fstab文件的奇数行另存为/tmp/fstab.1

wKiom1X-yiXSqA2vAAUbcZLtxtU895.jpg

        7、编写sed1.sh脚本,实现把tmp/test.txt中的大写字母D替换成小写的e(注意用-f选项)

wKioL1X-zGyCmt7YAAC_1CgOVu4269.jpg

8、echo一个文件路径给sed命令,取出其基名;进一步地,取出其路径名;

wKiom1X-yj3ArSg1AAEENHxE5H4336.jpg


   sed高级用法:保持空间(hold space),有相应的常用高级命令

    h:用模式空间中的内容覆盖保持空间的内容

H:把模式空间中的内容追加至保持空间中内容的后面

g:从保持空间中取到其内容,并将其覆盖模式空间中的内容

G:从保持空间中取到其内容,并将其追加在模式空间中的内容的后面

x:把保持空间和模式空间中的进行交换

n:读取匹配到的行的下一行至模式空间(会覆盖模式空间中的原有内容)

N:读取匹配到的行的下一行至模式空间,追加在模式空间中原有内容的后面

d:删除模式空间中的内容

D:删除多行模式空间中的首行


练习:

1、在tmp/test.txt文件中的每行后方添加空白行

wKioL1X-zIbDWGw0AACMENgYHTg420.jpg

2、tmp/test.txt文件保留最后一行

wKioL1X-zJGR3QKvAACTSjf5PSw722.jpg

        3、删除/tmp/passwd第三行到末尾的数据,并把bash替换为zsh

wKiom1X-ymDCVtEFAACzLbzsMIk259.jpg

4、保留/tmp/test.txt文件中的奇数行;

wKiom1X-ym2BPGkLAACxXx7oyxo925.jpg

5、倒序排列tmp/test.txt文件

wKioL1X-zLXAH7o5AAEWJPHTOEY186.jpg

6、保留tmp/test.txt文件倒数2行

wKioL1X-zMCRp0G_AABJZvKx45s482.jpg

         注意理解:$!N是对末尾行不执行N命令,其他行执行N命令

                   $!D是对末尾行不执行D命令,对其他行执行D命令

        7、显示/tmp/fstab行号(注:场景比较少用,相对复杂了)

wKioL1X-zNmQ-OyKAAJ7TlHBods414.jpg

       awk工具,一般指gawk:强大的文本分析工具,对数据分析并生成报告。awk是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

       语法:

       awk [options] 'program' {filenames}

       awk '{pattern + action}' {filenames}

       pattern:要查找的内容

        action:找到匹配内容时所执行的一系列命令,常用的有:命令、控制语句、复合语句、输出(输入)语句等

      花括号({}):不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组


      awk内置变量与自定义变量

      常用内置变量

          $0:这个变量包含执行过程中当前行的文本内容

          $n:前记录的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段

          FS:输入字段分隔符 默认是空格

          NF:当前记录中的字段个数,就是有多少列

          NR:已经读出的记录数,就是行号,从1开始

          RS:输入的记录他隔符默 认为换行符

          FNR:当前记录数

          OFS:输出字段分隔符 默认也是空格

          ORS:输出的记录分隔符,默认为换行符

         ARGC:命令行参数个数

         ARGV:命令行参数数组

     FILENAME:当前输入文件的名字

       自定义变量

       使用-v选项,将外部值(并非来自stdin)传递给awk

      练习:

      1、输出tpm/passwd中第一字段和第七字段信息并且已分号隔开

wKiom1X-yrWwMfIkAAHFPHTeSV0470.jpg

      2、显示文本tpm/passwd中所有超过50个字符的行号,并显示内容

wKioL1X-zP2BdtKnAANDMR_TMws923.jpg

      注:$0表示整个记录(行)

      3、统计/tmp/passwd后10行:文件名,每行的行号,每行的列数,对应的完整行内容

wKiom1X-ytLxEmFcAAMxYZFMUSc436.jpg

      4、定义变量aaa,bbb,用awk输出变量

wKioL1X-zRqz27vZAAC4_sckm9Y497.jpg


     printf命令:标准格式输出命令,并不会自动加入换行符,如需换行需要手工加入换行符。而print命令是每个输出后自动增加一个换行符

     语法:printf([format_control_flg],arg) 

     format_control_flg:格式

     arg:区域

     修饰符:

     #:显示宽度

     -:左对齐

     +:显示数值的符号

    .#: 取值精度

     常见以下格式:

     %c: 单个字符的ASCII码

     %d, %i: 十进制整数

     %e, %E: 科学计数法显示数值

     %f: 浮点数

     %g, %G: 以科学计数法格式或浮点数格式显示数值

     %s: 显示字符串

     %u: 显示无符号整数

     %%: 显示%自身

   练习:

   1、显示磁盘情况并第一列默认右对齐

wKiom1X-yumBS4KIAAImbZWzFMw011.jpg

   2、对2.2222取整

wKioL1X-zTHipYTTAABGypuCYII602.jpg

   3、对2.2222取浮点数

wKioL1X-zT-yPDSKAABSLwcoF5Y847.jpg

     

     awk输出重定向

       >:重定向输出

       >>: 重定向输出,不清空文件,只追加

       | :打开一个管道输出到另一个命令进行操作

      注意特殊文件输出输入描述符,简单了解即可:

/dev/stdin: 标准输入

/dev/stdout: 标准输出

/dev/stderr: 错误输出

     练习:

     1、把/tmp/test.txt如果第一个列的值等于4,则把它输出到outtest文件中

wKiom1X-yyWBhM-XAACP-Z53Xzk734.jpg

     2、显示当前系统时间

wKioL1X-zW-D2VDCAADCmCiq4So862.jpg


     awk操作符

     算术操作符:+、-、*、/、**、^、%、负数(-)、正数(+)

     字符串操作符:空格 (连接)

     赋值操作符:=、+=、-=、*=、/=、%=、^=、**=、++、-- (注:模式自身是=号,写为/=/)

     比较操作符:<、<=、>、=>、==、!=、~、!~

     逻辑操作符:&&、||

     条件表达式运算:要到问号和冒号,格式:表达条件式1 ?表达式2:表达式3;

     相当于:

     {

     if (expression1)  

        expression2

      else

        expression3

      }

      练习:

      1、输入两个数值10,20,进行比较,取最大值

wKioL1X-zX3xJETmAAB7ugPMRwM230.jpg

      注解:如果$1大于$2,则把问号后面的那个表达式的值赋给max,否则就将冒号后面那个表达式的值赋给max

      2、输入两个数值10,20,进行比较,取最大值

wKiom1X-y06g-Yr5AAB1JP4A4Ws211.jpg


     awk数组

     awk数组:关联数组(associative arrays),下标可以是数字也可以是字符串。awk中的数组不必提前声明,也不必声明大小,可初始化数组元素用 0 或空串

     数字下标声明数组,如:

     array[1]="her"

     array[2]="your"

     array[3]="sunday"

     array[4]=2050

     字符下标声明数组,如:

     array["first"]="tom"

     array["second"]="jack"

     array["third"]="jerry"

     删除数组:delete array[数组|字符]

     遍历数组,需要使用特殊的结构:for (var in array) {for body}

     练习:

     1、统计tcp连接状态的个数($6也是最后一个字段,可以使用$NF)

wKiom1X-y1yRWEgzAAHsWxyUxys874.jpg

     2、统计/var/log/httpd/access_log访问所有本地的IP及个数

wKioL1X-zeyTJcb2AADiRNFULHU635.jpg


     awk内置函数

     主要有以下几种:算数函数、字符串函数、其它一般函数、时间函数

     常用算术函数

     exp( x ):返回 x 幂函数

     sqrt( x ):返回 x 平方根

     int( x ):返回 x 的截断至整数的值

     常用字符串函数

     split( String, A, [Ere] ):将string表示的字符串以A分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从0开始的序列

     length([string]):返回string字符串中字符的个数

     substr(string, start [, length]):取string字符串中的子串,从start开始,取length个;start从1开始计数

     常用一般函数

     getline [ Variable ]:将 Variable 参数指定的变量设置为从当前输入文件读取的下一个输入记录

     常用时间函数

     systime():取系统当前时间

     练习:

     1、显示所有tcp连接ip

wKiom1X-y76Bmt3tAAF4meWZuWg102.jpg

     awk函数调用

     格式:function name(parameter1,parameter2,...) {return expression(表达式) }

     练习:

     1、求/tmp/function文件中三组整数的和

wKiom1X-y9KTaoFhAAKtwHABIzA605.jpg


    awk模式,常用有以下几种:

    /正则表达式/:使用通配符的扩展集。 

    关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试 

    模式匹配表达式:用运算符~(匹配)和~!(不匹配)

    BEGIN语句块、pattern语句块、END语句块

    

    awk控制语句

    条件判断:if-else

    语法:if (condition) {then-body} else {[ else-body ]}

    练习:

    1、显示/tmp/test.txt文件中大于2列打印bad,小于100打印ok

wKioL1X-zh_ihqbIAAFkqMgRNE0199.jpg

    2、显示/tmp/passwd文件中若用户是root则显示“admin”否则显示为“Common user”

wKiom1X-zBSR0i9AAAEsmw720qg840.jpg

    

    循环语句:while、do-while、for、case

    while循环语法: while (condition){statement1; statment2; ...}

    do-whil循环语法:do {do-while body} while (condition)

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

    case语句语法:switch (expression) {case VALUE or /RGEEXP/: statement1;... default: stementN}

    练习:(以下有多种实现方式,下面只是针对循环语句练习)

    1、统计1-100的和(使用while语句)

wKioL1X-zmGSO3ueAAB4B-1-2ig104.jpg

    2、统计1-100的和(使用do-while语句)

wKioL1X-zmzQtkptAABuTjbBpNs176.jpg

    3、显示字符串小于等于4(使用do-while语句)

wKioL1X-znmAaVGQAACJRbyFFhE322.jpg

    4、统计1-100的和(使用for语句)

wKioL1X-zoSyzhDkAABr1_rF0mA616.jpg

    5、显示字符串大于等于4的(使用for语句)

wKiom1X-zFKB9c4cAAE_zJmfB60961.jpg

    循环控制:continue、break、next

    next:提前结束对本行文本的处理,并接着处理下一行

    练习:

    1、显示/tmp/fstab文件,i变量的初始值为3,若i小于可等于NF(当前记录中的字段数),则执行打印语句I am out!,且i增加1,若变量大于3则跳出循环

wKioL1X-zp2Qy12BAAKNO3wL1So670.jpg

    2、显示/tmp/test.txt文件,i变量的初始值为3,若i小于可等于NF(当前记录中的字段数),则执行打印语句please next lines,且i增加1,若变量等于0则跳出循环

wKiom1X-zG7R7H1PAACkU6FYqDY024.jpg

    3、显示/etc/passwd文件其ID号为奇数的用户:

wKioL1X-zrayEW2cAAFSnoIt7Pk281.jpg