• Linux Shell脚本一文读懂


    目录

    1、什么是shell

    1.1 第一个shell脚本

     2、Shell 变量

    2.1 Shell 变量命名规则

    2.2 Shell 变量类型

    2.2.1 用户变量

    2.2.2 系统变量

    2.2.3 环境变量

    3、Shell 参数传递

    3.1 命令行式参数传递

    3.2 getopts参数传递

     4、Shell 数组

    4.1  关联数组(等同于键值对Map)

    5、Shell 运算符

    5.1 算数运算符

    5.1.1 算术运算符总结

     5.2 关系运算符

    5.2.1 关系运算符总结

     5.3 布尔运算符

    5.4 逻辑运算符

    5.5 字符串运算符

    5.6 文件测试运算符

    6、Shell 流程控制

    6.1 条件语句

    6.2 多路分支语句

    6.3 循环语句 

    6.4 循环控制语句 

     7、Shell 函数

     8、Shell test

    数值测试

    字符串测试

    文件测试

    9、Shell 正则表达式 

    正则表达式基本元字符

    正则表达式拓展元字符

     10、Shell grep

    grep使用

    grep正则过滤

    grep正则升级版本egrep

    11、Shell sed

    11.1 Sed 用法之打印

    11.2 Sed 用法之搜索替换

    11.3 Sed  用法之多重编辑选型

    11.4 Sed 用法之地址

    11.5、sed命令用法及解析

    12、Shell awk

    awk 简介

    awk 语法格式

    awk 记录与字段相关内部变量:

    awk 关系运算符

    awk 比较表达式

    awk 算术运算

    awk 常见使用总结

    13、Shell Expect

    1、什么是shell

            shell脚本是一个文件,里面存放的是特定格式的指令,系统可以使用脚本解析器翻译或解析指令并执行(无需编译)。shell脚本的本质是 shell命令的有序集合

    1.1 第一个shell脚本

    Shell 脚本创建总共分为三步:

    • 创建shell脚本

       

    编辑Shell脚本内容如下hello_shell.sh:

    1. #! /bin/bash
    2. echo "Hello World, Shell"
    • shell脚本权限赋值

    • 执行shell脚本

     2、Shell 变量

    shell允许用户建立变量存储数据,但不支持数据类型(整型、字符、浮点型), 任何赋给变量的值都被解释为一串字符。

    2.1 Shell 变量命名规则

    • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
    • 中间不能有空格,可以使用下划线 _。
    • 不能使用标点符号。
    • 不能使用bash里的关键字(可用help命令查看保留关键字)。

    2.2 Shell 变量类型

    Shell变量类型主要分为三大类:1、用户变量、2、系统变量、3、环境变量

    2.2.1 用户变量

    用户自定义变量,通常使用全大写定义变量名,方便识别;

    实例:定义用户自定义变量MSG,并输出。

    1. #! /bin/bash
    2. MSG="用户自定义变量"
    3. echo "$MSG"

    实例效果截图:

    2.2.2 系统变量

    用于对参数判断和命令返回值判断时使用

    实例:输出系统变量:$0 

    1. #!/bin/bash
    2. echo "脚本名称为: $0"

     实例效果截图:

    系统变量总结 

    $0   #当前脚本的名称
    $n   #传递给脚本或函数的第n个参数,n=1,2,…9
    $#   #传递给脚本或函数的参数个数
    $*   #传递给脚本或函数的所有参数:“$1,$2,……$9” 整体传递
    $@   #传递给脚本或函数的所有参数:“$1”,“$2”,……“$9” 分开传递
    $?   #命令或程序执行完后的状态,返回0表示执行成功
    $$   #当前脚本程序的PID号

    2.2.3 环境变量

    在程序运行时需要设置。

    实例:输出脚本当前执行位置

    1. #! /bin/bash
    2. path= `pwd`
    3. echo $path

     实例效果截图:

    环境变量总结

    PATH      #shell搜索路径,以冒号为分割
    HOME      #/etc/passwd文件中列出的用户主目录 
    SHELL     #当前Shell类型
    USER      #当前用户名
    ID        #当前用户id信息
    PWD       #当前所在路径
    TERM      #当前终端类型
    HOSTNAME    #当前主机名;
    PS1         #定义主机命令提示符
    HISTSIZE    #历史命令大小,可通过HISTTIMEFORMAT变量设置命令执行时间
    RANDOM      #随机生成一个0至32767的整数
    HOSTNAME    #主机名
     

     温馨提示:变量名与等号之间是不允许存在空格,否则提示'Common not found 指定未找到错误'。

    错误展示例:

    1. # 错误变量定义,变量与等号之间存在空格,弹出错误信息:为找到pwd 指令
    2. path = `pwd`
    3. echo "$path"
    4. # 正确变量定义, 变量与等号之间不存在空格。
    5. path=`pwd`
    6. echo "$path"

    3、Shell 参数传递

    Shell 参数传递主要分为两种:1、命令行式参数传递,2、getopts参数传递

    3.1 命令行式参数传递

    温馨提示:采用命令行式参数传递值得注意的是,$0获取到的是脚本路径以及脚本名,后面按顺序获取参数,当参数超过10个时(包括10个),需要使用${10},${11}....才能获取到参数,但是一般很少会超过10个参数的情况。

    示例:创建命令行式参数传递Shell脚本,commond_param.sh

    1. #! /bin/bash
    2. echo "脚本$0"
    3. echo "第一个参数$1"
    4. echo "第二个参数$2"

    未传参效果截图:

    传参效果截图:传递两个参数,分别为110 和119 

     特殊字符参数整理

    参数处理说明
    $#传递到脚本的参数个数
    $*以一个单字符串显示所有向脚本传递的参数。
    如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
    $$脚本运行的当前进程ID号
    $!后台运行的最后一个进程的ID号
    $@与$*相同,但是使用时加引号,并在引号中返回每个参数。
    如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
    $-显示Shell使用的当前选项,与set命令功能相同。
    $?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

    示例:创建特殊字符串Shell脚本,special_str.sh

    1. #! /bin/bash
    2. echo "Shell 传递参数实例!";
    3. echo "第一个参数为:$1";
    4. echo "参数个数为:$#";
    5. echo "传递的参数作为一个字符串显示:$*";

    调用special_str脚本,并传递参数:110 119 120

    知识点拓展: $* 与 $@ 区别

    • 相同点:都是引用所有参数。
    • 不同点:$* 接受多个参数使用空格进行连接,显示一个参数,$@接受多个参数转化为数组接受,$*和$@只有在双引号中体现出来。

    示例:

    1. #! /bin/bash
    2. echo "-- \$* 演示 ---"
    3. for i in "$*"; do
    4. echo $i
    5. done
    6. echo "-- \$@ 演示 ---"
    7. for i in "$@"; do
    8. echo $i
    9. done

    3.2 getopts参数传递

    getopts 可以获取用户在命令下的参数,然后根据参数进行不同的提示或者不同的执行。

    语法格式:getopts option_string variable

     option_string 形式参数名称   variable 遍历形式参数变量名称

    各个形式参数之间可以通过冒号 : 进行分隔,也可以直接相连接,  表示选项后面必须带有形式参数的实际值,如果没有可以不加实际值进行传递。

    示例:创建getopts 参数传递Shell脚本,getopts_sh.sh

    1. #! /bin/bash
    2. while getopts ":a:b:c:" opt
    3. do
    4. case $opt in
    5. a)
    6. echo "参数a的值$OPTARG"
    7. ;;
    8. b)
    9. echo "参数b的值$OPTARG"
    10. ;;
    11. c)
    12. echo "参数c的值$OPTARG"
    13. ;;
    14. ?)
    15. echo "未知参数"
    16. exit 1;;
    17. esac
    18. done

    调用getopts_sh.sh 脚本,并传递参数

     4、Shell 数组

    Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。

    Bash Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:

    array_name=(value1 value2 ... valuen)

    示例:创建数组实例化并遍历数组对象,array_sh.sh脚本

    1. #! /bin/bash
    2. # 数组实例化一
    3. one_array=(A B C D E)
    4. # 数组实例化二
    5. two_array[0]=1
    6. two_array[1]=2
    7. two_array[2]=3
    8. two_array[3]=4
    9. # 数组遍历
    10. echo "第一个元素为: ${one_array[0]}"
    11. echo "第二个元素为: ${one_array[1]}"
    12. echo "第三个元素为: ${one_array[2]}"
    13. echo "第四个元素为: ${one_array[3]}"

    调用array_sh.sh 脚本

    4.1  关联数组(等同于键值对Map)

    Bash Shell支持关联数组,可以使用任意的字符串、或者整数作为下标来访问数组元素。

    关联数组使用 declare 命令来声明,语法格式如下:

    declare -A array_name

    温馨提示:

    • -A 选项就是用于声明一个关联数组。
    • 关联数组的键是唯一的。

    示例:创建关联数组实例化并遍历关联数组对象,real_array_sh.sh脚本

    1. #! /bin/bash
    2. # 关联数组实例化方式一
    3. declare -A site=(["google"]="www.google.com" ["baidu"]="www.baidu.com" ["taobao"]="www.taobao.com")
    4. # 关联数组实例化方式二
    5. declare -A siteCopy
    6. siteCopy["google"]="www.google.com"
    7. siteCopy["baidu"]="www.baidu.com"
    8. siteCopy["taobao"]="www.taobao.com"
    9. # 通过关联数组键访问指定元素
    10. echo ${site["baidu"]}
    11. # 输出关联数组元素
    12. echo "关联数组元素: ${site[*]}"
    13. echo "Copy关联数组元素: ${site[@]}"
    14. # 输出关联数组元素的键值
    15. echo "关联数组键值: ${!site[*]}"
    16. echo "Copy 关联数组键值: ${!site[@]}"
    17. # 输出关联数组元素的大小
    18. echo "关联数组大小: ${#site[*]}"
    19. echo "关联数组大小: ${#site[@]}"

    调用real_array_sh.sh 脚本

    5、Shell 运算符

    Bash Shell 支持的运算符如下:

    • 算数运算符
    • 关系运算符
    • 布尔运算符
    • 字符串运算符
    • 文件测试运算符

    5.1 算数运算符

    Bash Shell 不支持数学运算【加、减、乘、除】,但是可以通过Bash Shell 命令实现,例如 awk 和 expr,expr 最常用。

    示例:创建算术运算符脚本,arith_test.sh

    1. #! /bin/bash
    2. a=10
    3. b=20
    4. # 注意使用的是反引号 ` 而不是单引号 '
    5. # 表达式和运算符之间要有空格
    6. val=`expr $a + $b`
    7. echo "a + b : $val"
    8. val=`expr $a - $b`
    9. echo "a - b : $val"
    10. val=`expr $a \* $b`
    11. echo "a * b : $val"
    12. val=`expr $b / $a`
    13. echo "b / a : $val"
    14. val=`expr $b % $a`
    15. echo "b % a : $val"
    16. # 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]
    17. if [ $a == $b ]
    18. then
    19. echo "a 等于 b"
    20. fi
    21. if [ $a != $b ]
    22. then
    23. echo "a 不等于 b"
    24. fi

     调用arith_test.sh脚本

    5.1.1 算术运算符总结

    算符说明举例
    +加法`expr $a + $b` 结果为 30。
    -减法`expr $a - $b` 结果为 -10。
    *乘法`expr $a \* $b` 结果为  200。
    /除法`expr $b / $a` 结果为 2。
    %取余`expr $b % $a` 结果为 0。
    =赋值a=$b 把变量 b 的值赋给 a。
    ==相等。用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。
    !=不相等。用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。

     5.2 关系运算符

    关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

    示例:创建关系运算符脚本,real_test.sh

    1. #!/bin/bash
    2. a=10
    3. b=20
    4. if [ $a -eq $b ]
    5. then
    6. echo "$a -eq $b : a 等于 b"
    7. else
    8. echo "$a -eq $b: a 不等于 b"
    9. fi
    10. if [ $a -ne $b ]
    11. then
    12. echo "$a -ne $b: a 不等于 b"
    13. else
    14. echo "$a -ne $b : a 等于 b"
    15. fi
    16. if [ $a -gt $b ]
    17. then
    18. echo "$a -gt $b: a 大于 b"
    19. else
    20. echo "$a -gt $b: a 不大于 b"
    21. fi
    22. if [ $a -lt $b ]
    23. then
    24. echo "$a -lt $b: a 小于 b"
    25. else
    26. echo "$a -lt $b: a 不小于 b"
    27. fi
    28. if [ $a -ge $b ]
    29. then
    30. echo "$a -ge $b: a 大于或等于 b"
    31. else
    32. echo "$a -ge $b: a 小于 b"
    33. fi
    34. if [ $a -le $b ]
    35. then
    36. echo "$a -le $b: a 小于或等于 b"
    37. else
    38. echo "$a -le $b: a 大于 b"
    39. fi

    调用real_test.sh 脚本

    5.2.1 关系运算符总结

    运算符说明举例
    -eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 false。
    -ne检测两个数是否不相等,不相等返回 true。[ $a -ne $b ] 返回 true。
    -gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
    -lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
    -ge检测左边的数是否大于等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
    -le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。

     5.3 布尔运算符

    布尔运算符总结

    运算符说明举例
    !非运算,表达式为 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。

    示例:创建布尔运算符脚本 

    1. #!/bin/bash
    2. a=10
    3. b=20
    4. if [ $a != $b ]
    5. then
    6. echo "$a != $b : a 不等于 b"
    7. else
    8. echo "$a == $b: a 等于 b"
    9. fi
    10. if [ $a -lt 100 -a $b -gt 15 ]
    11. then
    12. echo "$a 小于 100 且 $b 大于 15 : 返回 true"
    13. else
    14. echo "$a 小于 100 且 $b 大于 15 : 返回 false"
    15. fi
    16. if [ $a -lt 100 -o $b -gt 100 ]
    17. then
    18. echo "$a 小于 100 或 $b 大于 100 : 返回 true"
    19. else
    20. echo "$a 小于 100 或 $b 大于 100 : 返回 false"
    21. fi
    22. if [ $a -lt 5 -o $b -gt 100 ]
    23. then
    24. echo "$a 小于 5 或 $b 大于 100 : 返回 true"
    25. else
    26. echo "$a 小于 5 或 $b 大于 100 : 返回 false"
    27. fi

    调用上传脚本,结果输出

    1. 10 != 20 : a 不等于 b
    2. 10 小于 10020 大于 15 : 返回 true
    3. 10 小于 10020 大于 100 : 返回 true
    4. 10 小于 520 大于 100 : 返回 false

    5.4 逻辑运算符

    运算符说明举例
    &&逻辑的 AND[[ $a -lt 100 && $b -gt 100 ]] 返回 false
    ||逻辑的 OR[[ $a -lt 100 || $b -gt 100 ]] 返回 true

    示例:创建逻辑运算符脚本  

    1. #!/bin/bash
    2. a=10
    3. b=20
    4. if [[ $a -lt 100 && $b -gt 100 ]]
    5. then
    6. echo "返回 true"
    7. else
    8. echo "返回 false"
    9. fi
    10. if [[ $a -lt 100 || $b -gt 100 ]]
    11. then
    12. echo "返回 true"
    13. else
    14. echo "返回 false"
    15. fi

    调用上传脚本,结果输出

    1. 返回 false
    2. 返回 true

    5.5 字符串运算符

    运算符说明举例
    =检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
    !=检测两个字符串是否不相等,不相等返回 true。[ $a != $b ] 返回 true。
    -z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
    -n检测字符串长度是否不为 0,不为 0 返回 true。[ -n "$a" ] 返回 true。
    $检测字符串是否不为空,不为空返回 true。[ $a ] 返回 true。

    示例:创建字符串运算符脚本   

    1. #!/bin/bash
    2. a="abc"
    3. b="efg"
    4. if [ $a = $b ]
    5. then
    6. echo "$a = $b : a 等于 b"
    7. else
    8. echo "$a = $b: a 不等于 b"
    9. fi
    10. if [ $a != $b ]
    11. then
    12. echo "$a != $b : a 不等于 b"
    13. else
    14. echo "$a != $b: a 等于 b"
    15. fi
    16. if [ -z $a ]
    17. then
    18. echo "-z $a : 字符串长度为 0"
    19. else
    20. echo "-z $a : 字符串长度不为 0"
    21. fi
    22. if [ -n "$a" ]
    23. then
    24. echo "-n $a : 字符串长度不为 0"
    25. else
    26. echo "-n $a : 字符串长度为 0"
    27. fi
    28. if [ $a ]
    29. then
    30. echo "$a : 字符串不为空"
    31. else
    32. echo "$a : 字符串为空"
    33. fi

    调用上传脚本,结果输出

    1. abc = efg: a 不等于 b
    2. abc != efg : a 不等于 b
    3. -z abc : 字符串长度不为 0
    4. -n abc : 字符串长度不为 0
    5. abc : 字符串不为空

    5.6 文件测试运算符

    文件测试运算符用于检测 Unix 文件的各种属性。

    操作符说明举例
    -b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
    -c file检测文件是否是字符设备文件,如果是,则返回 true。[ -c $file ] 返回 false。
    -d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
    -f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
    -g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。
    -k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。
    -p file检测文件是否是有名管道,如果是,则返回 true。[ -p $file ] 返回 false。
    -u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。
    -r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。
    -w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。
    -x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。
    -s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。
    -e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true。

    其他检查符:

    • -S: 判断某文件是否 socket。
    • -L: 检测文件是否存在并且是一个符号链接。

    示例:创建文件测试运算符脚本   

    1. #!/bin/bash
    2. file="/home/shell/test.sh"
    3. if [ -r $file ]
    4. then
    5. echo "文件可读"
    6. else
    7. echo "文件不可读"
    8. fi
    9. if [ -w $file ]
    10. then
    11. echo "文件可写"
    12. else
    13. echo "文件不可写"
    14. fi
    15. if [ -x $file ]
    16. then
    17. echo "文件可执行"
    18. else
    19. echo "文件不可执行"
    20. fi
    21. if [ -f $file ]
    22. then
    23. echo "文件为普通文件"
    24. else
    25. echo "文件为特殊文件"
    26. fi
    27. if [ -d $file ]
    28. then
    29. echo "文件是个目录"
    30. else
    31. echo "文件不是个目录"
    32. fi
    33. if [ -s $file ]
    34. then
    35. echo "文件不为空"
    36. else
    37. echo "文件为空"
    38. fi
    39. if [ -e $file ]
    40. then
    41. echo "文件存在"
    42. else
    43. echo "文件不存在"
    44. fi

    调用上传脚本,结果输出

    1. 文件可读
    2. 文件可写
    3. 文件可执行
    4. 文件为普通文件
    5. 文件不是个目录
    6. 文件不为空
    7. 文件存在

    6、Shell 流程控制

    6.1 条件语句

    语法格式:

    1. if [condition1]; then
    2. ...
    3. elif [condition2]; then
    4. ...
    5. else
    6. ...
    7. fi

    示例:  查询当前docker 实例数,如果大于0,返回docker 实例数数量,否则什么也不返回。

    1. #! /bin/bash
    2. if [ $(ps -ef | grep -c "ssh") -gt 1 ]
    3. then
    4. echo "docker 当前实例化数量:$(ps -ef | grep -c 'ssh')"
    5. else
    6. echo "docker 当前实例化数量为0"
    7. fi

     调用docker_if.sh 脚本

     示例: 传入两个整数类型变量,比较两个变量的大小

    1. #! /bin/bash
    2. parame1=$1
    3. parame2=$2
    4. if [ $parame1 == $parame2 ]
    5. then
    6. echo "parame1 等于 parame2"
    7. elif [ $parame1 -gt $parame2 ]
    8. then
    9. echo "parame1 大于 parame2"
    10. elif [ $parame1 -lt $parame2 ]
    11. then
    12. echo "parame1 小于 parame2"
    13. else
    14. echo "没有符合的条件"
    15. fi

     调用if_elseif_test.sh脚本

    温馨提示:

    • 大于小于判断可以使用 -gt\-lt,也可以使用 >\<
    • 语句条件可以使用[...],也可以使用((...)) 

    6.2 多路分支语句

    语法格式:

    1. case $variable in
    2. "case1")
    3. .......
    4. ;;
    5. "case2")
    6. .......
    7. ;;
    8. "case3")
    9. ......
    10. ;;
    11. *)
    12. ......
    13. ;;
    14. esac

    示例:  输入1-5任意数字,Base Shell 输出相关数字

    1. #! /bin/bash
    2. echo '输入 1 到 4 之间的数字:'
    3. echo '你输入的数字为:'
    4. read aNum
    5. case $aNum in
    6. 1) echo '你选择了 1'
    7. ;;
    8. 2) echo '你选择了 2'
    9. ;;
    10. 3) echo '你选择了 3'
    11. ;;
    12. 4) echo '你选择了 4'
    13. ;;
    14. *) echo '你没有输入 1 到 4 之间的数字'
    15. ;;
    16. esac

     执行input_num.sh 脚本

    6.3 循环语句 

    语法格式一:

    1. for var in con1 con2 con3 ...
    2. do
    3. ......
    4. done

     示例: 遍历数组对象

    1. #! /bin/bash
    2. one_array=(A B C D E F)
    3. for loop in $one_array
    4. do
    5. echo "当前值为:$loop"
    6. done
    7. for var in A B C D E F
    8. do
    9. echo "当前值为:$var"
    10. done

    调用test_one.sh 脚本

    语法格式二:

    1. while [condition]
    2. do
    3. ......
    4. done

    示例:如果 int 小于等于 5,那么条件返回真。int 从 1 开始,每次循环处理时,int 加 1。

    1. #! /bin/bash
    2. int=1
    3. while(( $int<=5 ))
    4. do
    5. echo $int
    6. let "int++"
    7. done

     调用test_two.sh 脚本

    6.4 循环控制语句 

    1. break #终止执行所有循环
    2. continue #终止该次循环,进行下次循环

     示例:break 使用

    1. #!/bin/bash
    2. while :
    3. do
    4. echo -n "输入 1 到 5 之间的数字:"
    5. read aNum
    6. case $aNum in
    7. 1|2|3|4|5) echo "你输入的数字为 $aNum!"
    8. ;;
    9. *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
    10. break
    11. ;;
    12. esac
    13. done

     示例:continue  使用 

    1. #!/bin/bash
    2. while :
    3. do
    4. echo -n "输入 1 到 5 之间的数字: "
    5. read aNum
    6. case $aNum in
    7. 1|2|3|4|5) echo "你输入的数字为 $aNum!"
    8. ;;
    9. *) echo "你输入的数字不是 1 到 5 之间的!"
    10. continue
    11. echo "游戏结束"
    12. ;;
    13. esac
    14. done

     7、Shell 函数

    Base Shell可以用户定义函数,然后在shell脚本中可以随便调用。

    语法格式:

    1. [ function ] funname [()]
    2. {
    3. action;
    4. [return int;]
    5. }

    温馨提示: 

    • 可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
    • 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。

    示例:调用Shell脚本,输出www.baidu.com

    1. #! /bin/bash
    2. #定义函数
    3. function url {
    4. echo "www.baidu.com"
    5. }
    6. #调用函数
    7. url

    效果截图:

     示例:调用Shell脚本,输出参数值之和

    1. #! /bin/bash
    2. #定义函数:获取参数的和
    3. function get_sum() {
    4. # 变量只在函数内生效。属于局部变量
    5. local sum=0
    6. for n in $@
    7. do
    8. ((sum+=n))
    9. done
    10. return $sum
    11. }
    12. #调用函数并传递参数
    13. get_sum 10 2 5 7 9 12 50
    14. echo $?

    效果截图:

     特殊字符参数处理:

    参数处理说明
    $#传递到脚本或函数的参数个数
    $*以一个单字符串显示所有向脚本传递的参数
    $$脚本运行的当前进程ID号
    $!后台运行的最后一个进程的ID号
    $@与$*相同,但是使用时加引号,并在引号中返回每个参数。
    $-显示Shell使用的当前选项,与set命令功能相同。
    $?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

    取消函数 :unset  自定义函数名称 #取消函数

     8、Shell test

    test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

    数值测试

    参数说明
    -eq等于则为真
    -ne不等于则为真
    -gt大于则为真
    -ge大于等于则为真
    -lt小于则为真
    -le小于等于则为真

     示例:比较两个参数大小

    1. #! /bin/bash
    2. num1=$1
    3. num2=$2
    4. if test $[num1] -eq $[num2]
    5. then
    6. echo '两个数相等!'
    7. else
    8. echo '两个数不相等!'
    9. fi
    10. [ro

    效果截图:

    字符串测试

    参数说明
    =等于则为真
    !=不相等则为真
    -z 字符串字符串的长度为零则为真
    -n 字符串字符串的长度不为零则为真

     示例:比较两个字符串是否相等

    1. #! /bin/bash
    2. num1=$1
    3. num2=$2
    4. if test $num1 = $num2
    5. then
    6. echo '两个字符串相等!'
    7. else
    8. echo '两个字符串不相等!'
    9. fi

    效果截图:

    文件测试

    参数说明
    -e 文件名如果文件存在则为真
    -r 文件名如果文件存在且可读则为真
    -w 文件名如果文件存在且可写则为真
    -x 文件名如果文件存在且可执行则为真
    -s 文件名如果文件存在且至少有一个字符则为真
    -d 文件名如果文件存在且为目录则为真
    -f 文件名如果文件存在且为普通文件则为真
    -c 文件名如果文件存在且为字符型特殊文件则为真
    -b 文件名如果文件存在且为块特殊文件则为真

     示例:判断指定文件夹是否存在

    1. #! /bin/bash
    2. cd /home
    3. if test -e ./shell
    4. then
    5. echo '文件已存在!'
    6. else
    7. echo '文件不存在!'
    8. fi

    效果截图:

    9、Shell 正则表达式 

    正则表达式(regular expression, RE)是一种字符模式,用于在查找过程中匹配指定的字符。

    正则表达式分为:

    • 正则表达式基本元字符
    • 正则表达式拓展元字符

    正则表达式基本元字符

    1. 基本正则表达式元字符
    2. 元字符
    3. 示例 功能 示例
    4. ^ 行首定位符 ^love
    5. $ 行尾定位符 love$
    6. . 匹配单个字符 l..e
    7. * 匹配前导符0到多次 ab*love
    8. .* 匹配任意多个字符(贪婪匹配)
    9. [] 匹配方括号中任意一个字符 [lL]ove
    10. [ - ] 匹配指定范围内的一个字符 [a-z0-9]ove
    11. [^] 匹配不在指定组里的字符 [^a-z0-9]ove
    12. \ 用来转义元字符 love\.
    13. \< 词首定位符 \<love
    14. \> 词尾定位符 love\>
    15. \(\) 匹配后的标签

    正则表达式拓展元字符

    1. 扩展正则表达式元字符 功能 示例
    2. + 匹配一次或多次前导字符 [a-z]+ove
    3. ? 匹配零次或一次前导字符 lo?ve
    4. a|b 匹配a或b love|hate
    5. x{m} 字符x重复m次 o{5}
    6. x{m,} 字符x重复至少m次 o{5,}
    7. x{m,n} 字符x重复m到n次 o{5,10}
    8. () 字符组 ov+ (ov)+

    示例:数字正则表达式判断

    1. #! /bin/bash
    2. num1=123
    3. # 正则判断, 需要使用[[]]
    4. [[ $num1 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"
    5. num2=1L1
    6. [[ $num2 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"
    7. num3=191
    8. [[ $num3 =~ ^[0-9]\.[0-9]+$ || $num3 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"

    效果截图:

     10、Shell grep

    grep命令是Globally search a Regular Expression and Print的缩写,表示进行全局的正则匹配并进行打印。

    grep使用

    1. [root@localhost ~]# grep '^#' /etc/ssh/ssh_config #过滤以#号开头的行
    2. [root@localhost ~]# grep -v '^#' /etc/ssh/ssh_config #-v:取反,表示反向查找
    3. [root@localhost ~]# grep 'sendenv' /etc/ssh/ssh_config
    4. [root@localhost ~]# grep -i 'sendenv' /etc/ssh/ssh_config #-i忽略大小写
    5. [root@localhost ~]# grep 'bash' /opt/test/ #过滤某个目录下面带有bash的行
    6. [root@localhost ~]# grep -r 'bash' /opt/test/ #-[r|R]表示递归查询

    grep正则过滤

    1. #grep基本正则匹配
    2. ^以什么开头
    3. [root@linux-server ~]# grep '^root' /etc/passwd
    4. root:x:0:0:root:/root:/bin/bash
    5. $以什么结尾
    6. [root@linux-server ~]# grep 'bash$' /etc/passwd
    7. root:x:0:0:root:/root:/bin/bash
    8. confluence:x:1000:1000:Atlassian Confluence:/home/confluence:/bin/bash
    9. to:x:1003:1003::/home/to:/bin/bash
    10. . 匹配单个字符
    11. [root@linux-server ~]# grep 'r..t' /etc/passwd
    12. root:x:0:0:root:/root:/bin/bash
    13. operator:x:11:0:operator:/root:/sbin/nologin
    14. ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    15. dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
    16. [root@linux-server ~]# grep 'r.t' /etc/passwd
    17. operator:x:11:0:operator:/root:/sbin/nologin
    18. sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    19. .* 任意多个字符(可以为0个字符)
    20. [root@linux-server ~]# grep 'r.*t' /etc/passwd
    21. root:x:0:0:root:/root:/bin/bash
    22. operator:x:11:0:operator:/root:/sbin/nologin
    23. ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    24. systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin polkitd:x:999:997:User for polkitd:/:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    25. sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
    26. tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
    27. apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
    28. abrt:x:1041:1041::/home/abrt:/bin/bash
    29. [] 匹配方括号中的任意一个字符
    30. [root@linux-server ~]# useradd Root
    31. [root@linux-server ~]# grep 'Root' /etc/passwd
    32. [root@linux-server ~]# grep '[Rr]oot' /etc/passwd
    33. root:x:0:0:root:/root:/bin/bash
    34. operator:x:11:0:operator:/root:/sbin/nologin
    35. Root:x:1000:1000::/home/Root:/bin/bash
    36. [ - ] 匹配指定范围内的一个字符
    37. [root@linux-server ~]# grep [a-z]oot /etc/passwd #a-z
    38. root:x:0:0:root:/root:/bin/bash
    39. operator:x:11:0:operator:/root:/sbin/nologin
    40. dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
    41. [^] 匹配不在指定组内的字符,非得意思
    42. [root@linux-server ~]# grep '[^0-9]' /etc/passwd
    43. [root@linux-server ~]# grep '[^0-9A-Z]oot' /etc/passwd
    44. root:x:0:0:root:/root:/bin/bash
    45. operator:x:11:0:operator:/root:/sbin/nologin
    46. dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
    47. #注意:^在[]内表示取反,^在[]外表示以什么开头

    grep正则升级版本egrep

    1. #扩展正则匹配---egrep
    2. 扩展正则表达式元字符 功能 示例
    3. + 匹配一次或多次前导字符 [a-z]+ove
    4. ? 匹配零次或一次前导字符 lo?ve
    5. a|b 匹配a或b love|hate
    6. x{m} 字符x重复m次 o{5}
    7. x{m,} 字符x重复至少m次 o{5,}
    8. x{m,n} 字符x重复m到n次 o{5,10}
    9. () 字符组 ov+ (ov)+
    10. egrep 支持正则表达式的拓展元字符
    11. [root@linux-server ~]# egrep '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/resolv.conf
    12. nameserver 192.168.246.2
    13. + 匹配一个或多个前导字符
    14. [root@linux-server ~]# egrep 'ro+t' /etc/passwd
    15. root:x:0:0:root:/root:/bin/bash
    16. operator:x:11:0:operator:/root:/sbin/nologin
    17. dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
    18. a|b 匹配a或b
    19. [root@linux-server ~]# netstat -anlp|egrep ':80|:22'
    20. [root@linux-server ~]# egrep 'root|jack' /etc/passwd
    21. root:x:0:0:root:/root:/bin/bash
    22. operator:x:11:0:operator:/root:/sbin/nologin
    23. jack1:x:1001:1001::/home/jack1:/bin/bash
    24. jack2:x:1002:1002::/home/jack2:/bin/bash
    25. x{m} 字符x重复m次
    26. [root@linux-server ~]# cat a.txt
    27. love
    28. love.
    29. loove
    30. looooove
    31. [root@linux-server ~]# egrep 'o{2}' a.txt
    32. loove
    33. looooove
    34. [root@linux-server ~]# egrep 'o{2,}' a.txt
    35. loove
    36. looooove
    37. [root@linux-server ~]# egrep 'o{6,7}' a.txt

    11、Shell sed

    sed:stream editor(流编辑器)的缩写是一种在线非交互式编辑器,它一次处理一行内容。这样不断重复,直到文件末尾。

    sed用途:自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

    sed 支持的正则表达式:

    • 使用基本元字符集 ^, $, ., *, [], [^], \< \>,
    • 使用扩展元字符集 ?, +, { }, |, ( )

    11.1 Sed 用法之打印

    sed 默认会输出文件的每一行,无论这行内容是否能匹配上匹配内容。

    语法格式:sed -r '匹配内容'  目标文件地址

    11.2 Sed 用法之搜索替换

    sed 默认打印目标文件每一行内容,并同时查找匹配内容的行记录,执行后续指令。默认是 p 打印(-n 不打印)

    示例:

    1. 示例文件
    2. [root@localhost ~]# vim test.txt
    3. MA Daggett, 341 King Road, Plymouth MA
    4. Alice Ford, 22 East Broadway, Richmond VA
    5. MA Thomas, 11345 Oak Bridge Road, Tulsa OK
    6. Terry Kalkas, 402 Ma Road, mA Falls PA
    7. Eric Adams, 20 Post Road, Sudbury mA
    8. Hubert Sims, 328A Brook Road, Roanoke VA
    9. Amy Wilde, 334 Ma Pkwy, Mountain View CA
    10. Sal Carpenter, 73 MA Street, Boston MA
    11. 1.搜索每一行匹配到MA的将第一个替换为Massachusetts:
    12. [root@localhost ~]# sed -r 's/MA/Massachusetts/' test.txt
    13. s:----查找
    14. 2.搜索每一行,找到所有的MA字符,进行全局替换为Massachusetts
    15. [root@localhost ~]# sed -r 's/MA/Massachusetts/g' test.txt
    16. 3.搜索每一行,找到所有的MA字符,进行全局替换为Massachusetts同时忽略大小写
    17. [root@localhost ~]# sed -r 's/MA/Massachusetts/gi' test.txt
    18. -i:忽略大小写
    19. 4.-n #静默输出(不打印默认输出)
    20. [root@localhost ~]# sed -r -n 's/MA/Massachusetts/' test.txt
    21. 案例:
    22. [root@localhost ~]# sed -r 's/SELINUX=disabled/SELINUX=enabled/' /etc/sysconfig/selinux
    23. (尽量用/etc/selinux/config中修改)

    11.3 Sed  用法之多重编辑选型

    示例:

    1. 1.使用多重指令:-e 给予sed多个命令的时候需要-e选项
    2. [root@localhost ~]# sed -r -e 's/MA/Massachusetts/' -e 's/PA/Pennsylvania/' test.txt
    3. 2.使用脚本文件:当有多个要编辑的项目时,可以将编辑命令放进一个脚本里,再使用sed搭配-f选项
    4. -f <script文件> 以选项中指定的script文件来处理输入的文本文件。
    5. [root@localhost ~]# vim s.sed
    6. s/MA/Massachusetts/
    7. s/PA/Pennsylvania/
    8. s/CA/California/
    9. s/VA/Virginia/
    10. s/OK/Oklahoma/
    11. [root@localhost ~]# sed -f s.sed test.txt
    12. 保存输出:
    13. [root@localhost ~]# sed -f s.sed test.txt > newfile.txt

    11.4 Sed 用法之地址

    地址用于决定对哪些  进行编辑。地址形式可以是数字、正则表达式或二者的结合。如果没有指定地址,sed将处理输入文件中的所有行。

    1. [root@localhost ~]# head /etc/passwd > passwd #生成测试文件
    2. [root@localhost ~]# sed -r '1d' passwd #d:表示删除-- 删除文件的第1行
    3. bin:x:1:1:bin:/bin:/sbin/nologin
    4. daemon:x:2:2:daemon:/sbin:/sbin/nologin
    5. [root@localhost ~]# sed -r '1,2d' passwd #删除文件的第1-2行 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    6. [root@localhost ~]# cat passwd
    7. root:x:0:0:root:/root:/bin/bash
    8. bin:x:1:1:bin:/bin:/sbin/nologin
    9. daemon:x:2:2:daemon:/sbin:/sbin/nologin
    10. ...
    11. [root@localhost ~]# sed -r '2,$d' passwd #删除第2行到最后一行
    12. root:x:0:0:root:/root:/bin/bash
    13. [root@localhost ~]# sed -r '/^root/d' passwd #匹配到root开头的行,删除此行
    14. bin:x:1:1:bin:/bin:/sbin/nologin
    15. daemon:x:2:2:daemon:/sbin:/sbin/nologin
    16. [root@localhost ~]# sed -r '/root/d' passwd #含有root的行都删除
    17. bin:x:1:1:bin:/bin:/sbin/nologin
    18. daemon:x:2:2:daemon:/sbin:/sbin/nologin
    19. [root@localhost ~]# sed -r '/bash/,3d' passwd #匹配到bash行,从此行到第3行删除
    20. adm:x:3:4:adm:/var/adm:/sbin/nologin
    21. [root@localhost ~]# cat -n passwd
    22. 1 root:x:0:0:root:/root:/bin/bash
    23. 2 bin:x:1:1:bin:/bin:/sbin/nologin
    24. 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    25. 4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    26. 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    27. 6 sync:x:5:0:sync:/sbin:/bin/sync
    28. 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    29. 8 halt:x:7:0:halt:/sbin:/sbin/halt
    30. 9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    31. 10 operator:x:11:0:operator:/root:/sbin/nologin
    32. [root@localhost ~]# sed -r '1~2d' passwd #删除奇数行,间隔两行删除
    33. bin:x:1:1:bin:/bin:/sbin/nologin
    34. adm:x:3:4:adm:/var/adm:/sbin/nologin
    35. sync:x:5:0:sync:/sbin:/bin/sync
    36. halt:x:7:0:halt:/sbin:/sbin/halt
    37. operator:x:11:0:operator:/root:/sbin/nologin
    38. [root@localhost ~]# sed '0~2d' passwd #删除偶数行,从0开始间隔2行删除
    39. passwd root:x:0:0:root:/root:/bin/bash
    40. daemon:x:2:2:daemon:/sbin:/sbin/nologin
    41. lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

    11.5、sed命令用法及解析

    1. 1.插入命令--i
    2. [root@localhost ~]# sed -r '2i\222222' passwd #在第2行插入
    3. 2.修改命令---c
    4. [root@localhost ~]# sed -r '4c\asfasdf' passwd
    5. 案例:
    6. [root@localhost ~]# sed -r '7c\SELINUX=enabled' /etc/sysconfig/selinux
    7. 3.选项 -i 会使得sed用修改后的数据替换原文件
    8. [root@localhost ~]# sed -r -i '7c\SELINUX=enabled' /etc/sysconfig/selinux #修改
    9. [root@localhost ~]# sed -r -i 's/SELINUX=enabled/SELINUX=disabled/' /etc/sysconfig/selinux #替换
    10. 4.由于在使用 -i 参数时比较危险, 所以我们在使用i参数时在后面加上.bak就会产生一个备份的文件,以防后悔
    11. [root@localhost ~]# sed -r -i.bak 's/root/ROOT/' passwd

    sed常见操作

    1. [root@localhost ~]# cp /etc/ssh/ssh_config .
    2. 1.删除配置文件中 # 号注释的行
    3. [root@localhost ~]# sed -ri '/^#/d' ssh_config
    4. 2.给文件行添加注释:
    5. [root@localhost ~]# sed -r '2,5s/^/#/' passwd
    6. 给所有行添加注释:
    7. [root@localhost ~]# sed -r 's/^/#/' passwd
    8. 3.给文件行添加和取消注释
    9. [root@localhost ~]# sed -ri s/^#baseurl/baseurl/g /etc/yum.repos.d/CentOS-Base.repo
    10. [root@localhost ~]# sed -r s/^mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOS-Base.repo

    12、Shell awk

    awk 简介

    awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自一个或多个文件,或其它命令的输出。可以在命令行中使用,但更多是作为脚本来使用。

    awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行操作。如果没有指定模式,则所有被操作所指定的行都被处理。

    awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。

    awk处理过程: 依次对每一行进行处理,然后输出,默认分隔符是空格或者tab键 
    

    awk 语法格式

    1. awk [options] 'commands' filenames
    2. options:
    3. -F 对于每次处理的内容,可以指定一个自定义的输入字段分隔符,默认的分隔符是空白字符(空格或 tab 键 )
    4. commands:
    5. BEGIN{} {} END{} filename
    6. 行处理前的动作 行内容处理的动作 行处理之后的动作 文件名
    7. BEGIN{}END{} 是可选项。
    8. 函数-BEGIN{}:读入文本之前要操作的命令。
    9. {}:主输入循环:用的最多。读入文件之后擦操作的命令。如果不读入文件都可以不用写。
    10. END{}:文本全部读入完成之后执行的命令。

    示例:

    awk -F":" '{print $1,$3}' /etc/passwd

    功能含义:读取/etc/passwd 文本内容,使用':'分号实现对/etc/passwd 文本内容的分隔,分隔的文本内容输出第一个和第三个字符。

    示例:

    1. [root@localhost ~]# awk 'BEGIN{ print 1/2} {print "ok"} END{print "----"}' /etc/hosts
    2. 0.5
    3. ok
    4. ok
    5. ----

    awk 记录与字段相关内部变量:

    1. 1.记录和字段
    2. awk 按记录处理:一行是一条记录,因为awk默认以换行符分开的字符串是一条记录。(默认\n换行符:记录分隔符)
    3. 字段:以字段分割符分割的字符串 默认是单个或多个“ ” tab键。
    4. 2.awk中的变量
    5. $0:表示整行;
    6. NF : 统计字段的个数
    7. $NF:是number finally,表示最后一列的信息
    8. RS:输入记录分隔符;
    9. ORS:输出记录分隔符。
    10. NR:打印记录号,(行号)
    11. FNR:可以分开,按不同的文件打印行号。
    12. FS : 输入字段分隔符,默认为一个空格。
    13. OFS 输出的字段分隔符,默认为一个空格。
    14. FILENAME 文件名 被处理的文件名称
    15. $1 第一个字段,$2第二个字段,依次类推...

    示例:

    1. FS(输入字段分隔符)---一般简写为-F(属于行处理前)
    2. [root@awk ~]# cat /etc/passwd | awk 'BEGIN{FS=":"} {print $1,$2}'
    3. root x
    4. bin x
    5. daemon x
    6. adm x
    7. lp x
    8. sync x
    9. shutdown x
    10. halt x
    11. mail x
    12. [root@awk ~]# cat /etc/passwd | awk -F":" '{print $1,$2}'
    13. root x
    14. bin x
    15. daemon x
    16. adm x
    17. lp x
    18. sync x
    19. shutdown x
    20. halt x
    21. mail x
    22. #注:如果-F不加默认为空格区分!
    23. ===============================================================
    24. OFS(输出字段分隔符)
    25. [root@awk ~]# cat /etc/passwd | awk 'BEGIN{FS=":";OFS=".."} {print $1,$2}'
    26. root..x
    27. bin..x
    28. daemon..x
    29. adm..x
    30. lp..x
    31. sync..x
    32. shutdown..x
    33. halt..x
    34. mail..x
    35. ======================================================================
    36. 1.创建两个文件
    37. [root@awk ~]# vim a.txt
    38. love
    39. love.
    40. loove
    41. looooove
    42. [root@awk ~]# vim file1.txt
    43. isuo
    44. IPADDR=192.168.246.211
    45. hjahj123
    46. GATEWAY=192.168.246.1
    47. NETMASK=255.255.255.0
    48. DNS=114.114.114.114
    49. NR 表示记录编号, 在awk将行做为记录, 该变量相当于当前行号,也就是记录号
    50. [root@awk ~]# awk '{print NR,$0}' a.txt file1.txt
    51. 1 love
    52. 2 love.
    53. 3 loove
    54. 4 looooove
    55. 5
    56. 6 isuo
    57. 7 IPADDR=192.168.246.211
    58. 8 hjahj123
    59. 9 GATEWAY=192.168.246.1
    60. 10 NETMASK=255.255.255.0
    61. 11 DNS=114.114.114.114
    62. FNR:表示记录编号, 在awk将行做为记录, 该变量相当于当前行号,也就是记录号(#会将不同文件分开)
    63. [root@awk ~]# awk '{print FNR,$0}' a.txt file1.txt
    64. 1 love
    65. 2 love.
    66. 3 loove
    67. 4 looooove
    68. 5
    69. 1 isuo
    70. 2 IPADDR=192.168.246.211
    71. 3 hjahj123
    72. 4 GATEWAY=192.168.246.1
    73. 5 NETMASK=255.255.255.0
    74. 6 DNS=114.114.114.114
    75. ===========================================================
    76. RS(输入记录分隔符)
    77. 1.创建一个文件
    78. [root@awk ~]# vim passwd
    79. root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologin
    80. [root@awk ~]# cat passwd | awk 'BEGIN{RS="bash"} {print $0}'
    81. root:x:0:0:root:/root:/bin/
    82. bin:x:1:1:bin:/bin:/sbin/nologin
    83. ORS(输出记录分隔符)
    84. 2.对刚才的文件进行修改
    85. [root@awk ~]# vim passwd
    86. root:x:0:0:root:/root:/bin/bash
    87. bin:x:1:1:bin:/bin:/sbin/nologin
    88. [root@awk ~]# cat passwd | awk 'BEGIN{ORS=" "} {print $0}'
    89. root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin
    90. ===========================================================
    91. NF:统计字段的个数
    92. [root@awk ~]# cat /etc/passwd | awk -F":" '{print NF}'
    93. 7
    94. 7
    95. 7
    96. 7
    97. $NF:打印最后一列
    98. [root@awk ~]# cat /etc/passwd | awk -F":" '{print $NF}'
    99. /bin/bash
    100. /sbin/nologin
    101. /sbin/nologin
    102. /sbin/nologin
    103. /sbin/nologin

    awk 关系运算符

    字符串的完全相等需要使用 ==。

    字符串需要使用双引号
    != 表示不等于

    示例:

    1. [root@awk ~]# awk -F":" '$NF == "/bin/bash"' /etc/passwd
    2. [root@awk ~]# awk -F":" '$1 != "root"' /etc/passwd

    awk 比较表达式

    1. 比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。
    2. 比较表达式使用关系运算符,用于比较数字与字符串。
    3. 关系运算符有
    4. < 小于 例如 x<y
    5. > 大于 x>y
    6. <= 小于或等于 x<=y
    7. == 等于 x==y
    8. != 不等于 x!=y
    9. >= 大于等于 x>=y

    示例:

    1. [root@awk ~]# awk -F":" '$3 == 0' /etc/passwd
    2. [root@awk ~]# awk -F":" '$3 < 10' /etc/passwd

    awk 算术运算

    支持表达式:+-*/%(模: 取余)^(幂:2^3)

    示例:

    awk -F: '$3 * 10 > 500' /etc/passwd
    

    awk 常见使用总结

    1.打印一个文件中的第2列和第5列

    # cat /etc/passwd | awk -F : '{print $2,$5}'

    2.打印指定行指定列的某个字符

    # free -m | awk 'NR==2 {print $2}'
    

    3.统计一个文件的行数

    # cat /etc/passwd | awk '{print NR}'

    获取根分区的使用量

    4.在awk中使用if条件判断

    1. i++===先赋值在运算
    2. ++i===先运算在赋值
    3. if语句:
    4. {if(表达式){语句;语句;...}}
    5. 实战案例:
    6. 显示管理员用户姓名
    7. [root@qfedu ~]# cat /etc/passwd | awk -F":" '{if($3==0) {print $1 " is administrator"}}'
    8. 统计系统用户数量
    9. [root@qfedu ~]# cat /etc/passwd | awk -F":" '{if($3>=0 && $3<=1000){i++}} END{print i}'

    5.在awk中使用for循环

    1. 每行打印两遍
    2. [root@qfedu ~]# awk '{for(i=1;i<=2;i++) {print $0}}' /etc/passwd
    3. root:x:0:0:root:/root:/bin/bash
    4. root:x:0:0:root:/root:/bin/bash
    5. bin:x:1:1:bin:/bin:/sbin/nologin
    6. bin:x:1:1:bin:/bin:/sbin/nologin
    7. daemon:x:2:2:daemon:/sbin:/sbin/nologin
    8. daemon:x:2:2:daemon:/sbin:/sbin/nologin

    6、数组遍历–用来统计网站日志的访问量。

    1. ++i:从1开始加,运算在赋值
    2. i++: 从0开始加,赋值在运算
    3. #按索引遍历:
    4. 1.先创建一个test文件,统计用户的数量
    5. # vim test.txt #将文件内容的第一个字段作为数组的值,通过索引获取到值
    6. root:x:0:0:root:/root:/bin/bash
    7. bin:x:1:1:bin:/bin:/sbin/nologin
    8. # cat test.txt | awk -F":" '{username[x++]=$1} END{for(i in username) {print i,username[i]}}'
    9. 0 root
    10. 1 bin
    11. #注意:变量i是索引

    7、真实案例

    1. #把要统计的对象作为索引,最后对他们的值进行累加,累加出来的这个值就是你的统计数量
    2. 1. 统计/etc/passwd中各种类型shell的数量
    3. # cat /etc/passwd | awk -F: '{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }'
    4. 2.统计nginx日志出现的状态码
    5. # cat access.log | awk '{stat[$9]++} END{for(i in stat){print i,stat[i]}}'
    6. 3.统计当前nginx日志中每个ip访问的数量
    7. # cat access.log | awk '{ips[$1]++} END{for(i in ips){print i,ips[i]}}'
    8. 4.统计某一天的nginx日志中的不同ip的访问量
    9. # cat access.log |grep '28/Sep/2019' | awk '{ips[$1]++} END{for(i in ips){print i,ips[i]}}'
    10. 5.统计nginx日志中某一天访问最多的前10个ip
    11. # cat access.log |grep '28/Sep/2019' | awk '{ips[$1]++} END{for(i in ips){print i,ips[i]}}' |sort -k2 -rn | head -n 10
    12. sort:排序,默认升序
    13. -k:指定列数
    14. -r:降序
    15. -n:以数值来排序
    16. 6.统计tcp连接的状态---下去自己查各个状态,包括什么原因造成的!
    17. # netstat -n | awk '/^tcp/ {tcps[$NF]++} END {for(i in tcps) {print i, tcps[i]}}'
    18. LAST_ACK 5 (正在等待处理的请求数)
    19. SYN_RECV 30
    20. ESTABLISHED 1597 (正常数据传输状态)
    21. FIN_WAIT1 51
    22. FIN_WAIT2 504
    23. TIME_WAIT 1057 (处理完毕,等待超时结束的请求数)

    8、经典案例

    1. UV与PV统计
    2. PV:即访问量,也就是访问您商铺的次数;
    3. 例如:今天显示有300 PV,则证明今天你的商铺被访问了300次。
    4. ================================================================
    5. UV:即访问人数,也就是有多少人来过您的商铺; #需要去重
    6. 例如:今天显示有50 UV,则证明今天有50个人来过你的商铺。
    7. =================================================================
    8. 1.根据访问IP统计UV
    9. # cat access.log | awk '{print $1}' |sort |uniq | wc -l
    10. uniq:去重
    11. -c:统计每行连续出现的次数
    12. 2.更具访问ip统计PV
    13. # cat access.log | awk '{print $1}' |wc -l
    14. 或者是url
    15. # cat access.log | awk '{print $7}' |wc -l
    16. 3.查询访问最频繁的URL
    17. # cat access.log | awk '{print $7}'|sort | uniq -c |sort -n -k 1 -r | more
    18. 4.查询访问最频繁的IP
    19. # cat access.log | awk '{print $1}'|sort | uniq -c |sort -n -k 1 -r | more

    功能实现:切割nginx的日志,统计PV\UV,出现次数最多的url等各种切割统计

    13、Shell Expect

    在实际工作中我们运行命令、脚本或程序时, 都需要从终端输入某些继续运行的指令,而这些输 入都需要人为的手工进行. 而利用 expect 则可以根据程序的提示, 模拟标准输入提供给程序, 从而实现自动化交互执 行. 这就是 expect .

    它是一个免费的编程工具, 用来实现自动的交互式任务, 而无需人为干预. 说白了 expect 就是一套用来实现自动交互功能的软件

    既:通过expect可以实现将交互式的命令变为非交互式执行,不需要人为干预(手动输入)

    No.1 expect的安装

    [root@qfedu ~] yum -y install expect

    No.2 expect的语法:
     

    1. 用法:
    2. 1)定义expect脚本执行的shell
    3. #!/usr/bin/expect -----类似于#!/bin/bash
    4. 2)spawn
    5. spawn是执行expect之后后执行的内部命令开启一个会话 #功能:用来执行shell的交互命令
    6. 3)expect ---相当于捕捉
    7. 功能:判断输出结果是否包含某项字符串(相当于捕捉命令的返回的提示)。没有捕捉到则会断开,否则等待一段时间后返回,等待通过timeout设置
    8. 4)send
    9. 执行交互动作,将交互要执行的命令进行发送给交互指令,命令字符串结尾要加上“\r”,#---相当于回车
    10. 5)interact
    11. 执行完后保持交互状态,需要等待手动退出交互状态,如果不加这一项,交互完成会自动退出
    12. 6)exp_continue
    13. 继续执行接下来的操作
    14. 7)timeout
    15. 返回设置超时时间(秒)

     实战非交互式ssh连接:

    1. 案例1:普通操作
    2. [root@qfedu script]# vim expect01.sh
    3. #!/usr/bin/expect
    4. spawn ssh root@192.168.246.115
    5. expect {
    6. "yes/no" { send "yes\r"; exp_continue }
    7. "password:" { send "1\r" };
    8. }
    9. interact
    10. [root@qfedu script]# chmod +x expect01.sh
    11. [root@qfedu script]# ./expect01.sh
    12. spawn ssh root@192.168.246.115
    13. root@192.168.246.115's password:
    14. Last login: Fri Aug 28 16:57:09 2019
    15. #如果添加interact参数将会等待我们手动交互进行退出。如果不加interact参数在登录成功之后会立刻退出。
    16. ============================================================================

  • 相关阅读:
    libcurl与分片传输、断点续传相关研究
    java 实现访问者模式
    利用CNN进行手写数字识别
    dubbo-admin在jdk1.8下报错问题(已解决)
    6.ClickHouse系列之配置分片集群
    服务器给前端实时推送数据轻量化解决方案eventSource+Springboot
    echarts的legend的小图标与文本垂直对齐
    【服务器搭建】教程三:怎样购买域名并怎样进行域名解析 来啦
    【动态规划】独立任务最优调度问题
    数据提取-数据提取软件
  • 原文地址:https://blog.csdn.net/zhouzhiwengang/article/details/127350327