• 三剑客-shell篇(讲解贼详细)


    目录

    前言

    一、基础正则表达式

    ​​​​​​​二、grep正则表达式

    2.1 过滤以m开头的行

    2.2 ​​​​​​​过滤以m结尾的行

    2.3 排除空行, 并打印行号

    2.4 匹配任意一个字符,不包括空行

    2.5 ​​​​​​​匹配所有

    2.6 ​​​​​​​匹配单个任意字符

    2.7 ​​​​​​​以点结尾的

    2.8 ​​​​​​精确匹配

    2.9 ​​​​​​​匹配有abc的行

    2.10 ​​​​​​​匹配数字所在的行"[0-9]"

    2.11 ​​​​​​​匹配所有小写字母[a-z]

    2.12 ​​​​​​​重复8三次

    2.13 ​​​​​​​重复数字8, 3-5次

    2.14 ​​​​​​​至少1次或1次以上

     ​​​​​​​三、sed文本处理

    3.1 ​​​​​​​sed命令格式

    3.2 ​​​​​​​sed正则使用

    3.3 sed选项参数

    3.4 ​​​​​​​sed内置命令参数

    3.5 ​​​​​​​先删除行,然后管道给后面的sed进行替换

    3.6 ​​​​​​​使用-e进行多次编辑修改操作

    3.7 ​​​​​​​打印命令`p`

    3.7.1 打印匹配halt的行

    3.7.1 打印第二行的内容

    3.7.3 打印最后一行

    3.8 ​​​​​​​追加命令`a`

    3.8.1 给30行添加配置 \t tab键(需要转义) \n 换行符

    3.9 ​​​​​​​修改命令`c`

    3.9.1 指定某行进行内容替换

    3.9.2 正则匹配对应内容, 然后进行替换

    3.9.3 非交互式修改指定的配置文件

    3.10 ​​​​​​​删除命令`d`

    3.10.1 指定删除第三行, 但不会改变文件内容

    3.10.2 从第三行删除到最后一行

    3.10.3 删除最后一行

    3.10.4 删除所有的行

    3.10.5 匹配正则进行该行删除

    3.11 ​​​​​​​插入命令`i`

    3.11.1 在文件的某一行上面添加内容

    3.12  ​​​​​​​写文件命令`w`

    3.12.1 将匹配到的行写入到新文件中

    3.12.2 将passwd文件的第二行写入到newfile中

    3.13 ​​​​​​​获取下一行命令`n`

    3.13.1 匹配root的行, 删除root行的下一列

    3.13.2 替换匹配root行的下一列

    3.14 sed高级参数

    3.14.1 将第一行的写入到暂存区, 替换最后一行的内容

    3.14.2 将第一行的写入到暂存区, 在最后一行调用暂存区的内容

    3.14.3 将第一行的内容删除但保留至暂存区, 在最后一行调用暂存区内容追加至于尾部

    3.14.4 将第一行的内容写入至暂存区, 从第二行开始进行重定向替换

    3.14.5 将第一行重定向至暂存区, 2-3行追加至暂存区, 最后追加调用暂存区的内容

    3.15 图解sed ‘1!G;h;$!d’ file

    3.15.1 sed简介

    3.15.2 sed执行流程图

    3.15.3 什么是Pattern Space,Hold Space

    3.15.4 图解sed ‘1!G;h;$!d’ file

    3.16 ​​​​​​​反向选择命令`!`

     3.16.1 除了第三行,其他全部删除[root@Shell ~]# sed -r '3!d' /etc/hosts

    3.17 ​​​​​​​sed匹配替换`g`

    3.17.1 替换每行出现的第一个root

    3.17.2 替换以root开头的行

    3.17.3 查找匹配到的行, 在匹配的行后面添加内容

    3.17.4 匹配包含有root的行进行替换

    3.17.5 匹配包含有root的行进行替换,忽略大小写

    3.17.6 在文本的每一行开头添加空格

    3.18 后向引用(重要)

    3.19 ​​​​​​​删除文件

    3.19.1 删除配置文件中#号开头的注释行, 如果碰到tab或空格是无法删除

    3.19.2 删除配置文件中含有tab键的注释行

    3.19.3 删除无内容空行

    3.19.4 删除注释行及空行

    3.20 ​​​​​​​给文件行添加注释

    3.20.1 将第二行到第六行加上注释信息

    3.20.2 将第二行到第六行最前面添加#注释符

    3.21 ​​​​​​​添加#注释符

    四、​​​​​​​Awk文本处理

    4.1 ​​​​​​​awk 的处理数据的方式

    4.2 ​​​​​​​`awk`的语法格式

    4.3 ​​​​​​​选项 options

    4.4 ​​​​​​​`awk`命令格式

    4.4.1 匹配 awk 'pattern' filename

    4.4.2 处理动作 awk '{action}' filename

    4.4.3 匹配+处理动作 awk 'pattern {action}' filename

    4.4.4 判断大于多少则输出什么内容 command |awk 'pattern {action}'

    4.5 ​​​​​​​Awk工作原理

    4.6 ​​​​​​​Awk内部变量

    4.6.1 `$0`保存当前记录的内容*

    4.6.2 `NR`记录输入总的编号(行号)*

    4.6.3 `FNR`当前输入文件的编号(行号)*

    4.6.4 `NF`保存行的最后一列*

    4.6.5 `FS`指定字段分割符, 默认是空格*

    4.6.6 `OFS`指定输出字段分隔符*

    4.6.7 `RS`输入记录分隔符,默认为换行符[了解]*

    4.6.8 `ORS`将文件以空格为分割每一行合并为一行[了解]*

    4.6.9 `print`格式化输出函数*

    4.7 ​​​​​​​Awk模式动作

    4.7.1 正则表达式*

    4.7.2 比较表达式*

    4.7.3 条件表达式*

    4.7.4 运算表达式*

    4.7.5 逻辑操作符和复合模式*

    4.8 ​​​​​​​`awk`示例1

    4.9 ​​​​​​​`awk`示例2

    4.10 ​​​​​​​Awk条件判断

    4.11 ​​​​​​​Awk循环语句

    4.11.1 while循环

    4.11.2 for循环

    4.12 ​​​​​​​awk数组概述

    4.12.1 统计`/etc/passwd`中各种类型`shell` 的数量*

    4.12.2 网站访问状态统计<当前时实状态ss>*

    4.12.3 统计当前访问的每个IP的数量<当前时实状态 netstat,ss>*

    4.13 ​​​​​​​Awk数组案例

    4.13.1 统计2018年01月25日,当天的PV量*

    4.13.2 统计15-19点的pv量

    4.13.3 统计2018年01月25日,一天内访问最多的10个IP*

    4.13.4 统计15-19点访问次数最多的10个IP

    4.13.5 统计2018年01月25日,访问大于100次的IP*

    4.13.6 统计2018年01月25日,访问最多的10个页面($request top 10)*

    4.13.7 统计2018年01月25日,每个URL访问内容总大小($body_bytes_sent)*

    4.13.8 统计2018年01月25日,每个IP访问状态码数量($status)*

    4.13.9 统计2018年01月25日,访问状态码为404及出现的次数($status)*

    4.13.10 统计2018年01月25日,8:30-9:00访问状态码是404*

    4.13.11 统计2018年01月25日,各种状态码数量,统计状态码出现的次数


    前言

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

    在大多数程序里,正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式,它将匹配被查找的行中任何位置出现的相同模式。在正则表达式中,元字符是最重要的概念。

    正则表达式的作用

    >1.Linux正则表达式`grep,sed,awk`

    2.大量的字符串文件需要进行配置,而且是非交互式的

    3.过滤相关的字符串,匹配字符串,打印字符串

    正则表达式注意事项

    >1.正则表达式应用非常广泛,存在于各种语言中,例如:php,python,java等。

    2.正则表达式和通配符特殊字符是有本质区别的。

    3.要想学好`grep、sed、awk`首先就要掌握正则表达式。

    ​​​​​​​一、基础正则表达式

    1. 元字符意义BRE,正则表达式实际就是一些特殊字符,赋予了他特定的含义。
    2. 正则表达式 描述
    3. \ 转义符,将特殊字符进行转义,忽略其特殊意义
    4. ^ 匹配行首,awk中,^则是匹配字符串的开始
    5. $ 匹配行尾,awk中,$则是匹配字符串的结尾
    6. ^$ 表示空行
    7. . 匹配除换行符\n之外的任意单个字符
    8. .* 匹配所有
    9. [ ] 匹配包含在[字符]之中的任意一个字符
    10. [^ ] 匹配[^字符]之外的任意一个字符
    11. [ - ] 匹配[]中指定范围内的任意一个字符
    12. ? 匹配之前的项1次或者0
    13. + 匹配之前的项1次或者多次
    14. * 匹配之前的项0次或者多次, .*
    15. () 匹配表达式,创建一个用于匹配的子串
    16. { n } 匹配之前的项n次,n是可以为0的正整数
    17. {n,} 之前的项至少需要匹配n次
    18. {n,m} 指定之前的项至少匹配n次,最多匹配m次,n<=m
    19. | 交替匹配|两边的任意一项ab(c|d)匹配abc或abd
    20. 特定字符:
    21. >[[:space:]] 空格
    22. [[:digit:]] [0-9]
    23. [[:lower:]] [a-z]
    24. [[:upper:]] [A-Z]
    25. [[:alpha:]] [a-Z]

    ​​​​​​​二、grep正则表达式

    2.1 过滤以m开头的行

    [root@Shell ~]# grep "^m" test.txt

    2.2 ​​​​​​​过滤以m结尾的行

    [root@Shell ~]# grep "m$" test.txt

    2.3 排除空行, 并打印行号

    [root@student ~]# grep -vn "^$" test.txt

    2.4 匹配任意一个字符,不包括空行

    [root@student ~]# grep "." test.txt

    2.5 ​​​​​​​匹配所有

    [root@student ~]# grep ".*" test.txt

    2.6 ​​​​​​​匹配单个任意字符

    [root@node1 ~]# grep "zhang" test.txt

    2.7 ​​​​​​​以点结尾的

    [root@student ~]# grep "\.$" test.txt

    2.8 ​​​​​​精确匹配

    [root@student ~]# grep -o "8*" test.txt

    2.9 ​​​​​​​匹配有abc的行

    [root@student ~]# grep "[abc]" test.txt

    2.10 ​​​​​​​匹配数字所在的行"[0-9]"

    [root@student ~]# grep "[0-9]" test.txt

    2.11 ​​​​​​​匹配所有小写字母[a-z]

    [root@student ~]# grep "[a-z]" test.txt

    2.12 ​​​​​​​重复8三次

    [root@student ~]# grep "8\{3\}" test.txt

    2.13 ​​​​​​​重复数字8, 3-5次

    [root@student ~]# grep -E "8{3,5}" test.txt

    2.14 ​​​​​​​至少1次或1次以上

    [root@student ~]# grep -E "8{1,}" test.txt

     ​​​​​​​三、sed文本处理

    sed是一个流编辑器, 非交互式的编辑器,它一次处理一行内容.

    处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space)

    接着用 sed 命令处理缓冲区中的内容,处理完成后, 把缓冲区的内容送往屏幕。

    接着处理下一行,这样不断重复,直到文件末尾。

    文件内容并没有改变,除非你 使用重定向存储输出。

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

    3.1 ​​​​​​​sed命令格式

    `sed [options] 'command' file(s)`

    3.2 ​​​​​​​sed正则使用

    1. 与 grep一样,sed 在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。
    2. 正则表达式是括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。
    3. 使用基本元字符集 ^, $, ., *, [], [^], \< \>, \(\), \{\}
    4. 使用扩展元字符集 ?, +, { }, |, ( )
    5. 使用扩展元字符的方式 \+ sed -r

    3.3 sed选项参数

    1. -e 允许多项编辑
    2. -n 取消默认的输出
    3. -i 直接修改对应文件
    4. -r 支持扩展元字符

    3.4 ​​​​​​​sed内置命令参数

    1. a 在当前行后添加一行或多行
    2. c 在当前行进行替换修改
    3. d 在当前行进行删除操作
    4. i 在当前行之前插入文本
    5. p 打印匹配的行或指定行
    6. n 读入下一输入行,从下一条命令进行处理
    7. ! 对所选行以外的所有行应用命令
    8. h 把模式空间里的内容重定向到暂存缓冲区
    9. H 把模式空间里的内容追加到暂存缓冲区
    10. g 取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容
    11. G 取出暂存缓冲区的内容,将其复制到模式空间,追加在原有内容后面

    3.5 ​​​​​​​先删除行,然后管道给后面的sed进行替换

    [root@Shell ~]# sed '1,9d' passwd |sed 's#root#alex#g'

    3.6 ​​​​​​​使用-e进行多次编辑修改操作

    [root@Shell ~]# sed -e '1,9d' -e 's#root#alex#g' passwd

    3.7 ​​​​​​​打印命令`p`

    3.7.1 打印匹配halt的行

    [root@Shell ~]# sed -n  '/halt/p' passwd

    3.7.1 打印第二行的内容

    [root@Shell ~]# sed -n  '2p' passwd

    3.7.3 打印最后一行

    [root@Shell ~]# sed -n  '$p' passwd

    3.8 ​​​​​​​追加命令`a`

    3.8.1 给30行添加配置 \t tab键(需要转义) \n 换行符

    [root@Shell ~]# sed -i  '30a listen 80;' passwd

    3.9 ​​​​​​​修改命令`c`

    3.9.1 指定某行进行内容替换

    [root@Shell ~]# sed  -i '7c SELINUX=Disabled' /etc/selinux/config

    3.9.2 正则匹配对应内容, 然后进行替换

    [root@Shell ~]# sed -i '/^SELINUX=/c SELINUX=Disabled' /etc/selinux/config

    3.9.3 非交互式修改指定的配置文件

    1. [root@Shell ~]# sed -ri '/UseDNS/cUseDNS no' /etc/ssh/sshd_config
    2. [root@Shell ~]# sed -ri '/GSSAPIAuthentication/c#GSSAPIAuthentication no' /etc/ssh/sshd_config
    3. [root@Shell ~]# sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config

    3.10 ​​​​​​​删除命令`d`

    3.10.1 指定删除第三行, 但不会改变文件内容

    1. [root@Shell ~]# sed '3d' passwd
    2. [root@Shell ~]# sed '3{d}' passwd

    3.10.2 从第三行删除到最后一行

    [root@Shell ~]# sed '3,$d' passwd

    3.10.3 删除最后一行

    [root@Shell ~]# sed '$d' passwd

    3.10.4 删除所有的行

    [root@Shell ~]# sed '1,$d' passwd

    3.10.5 匹配正则进行该行删除

    [root@Shell ~]# sed /mail/d passwd

    3.11 ​​​​​​​插入命令`i`

    3.11.1 在文件的某一行上面添加内容

    [root@Shell ~]# sed -i  '30i listen 80;' passwd

    3.12  ​​​​​​​写文件命令`w`

    3.12.1 将匹配到的行写入到新文件中

    [root@Shell ~]# sed -n '/root/w newfile' passwd

    3.12.2 将passwd文件的第二行写入到newfile中

    [root@Shell ~]# sed -n '2w newfile' passwd

    3.13 ​​​​​​​获取下一行命令`n`

    3.13.1 匹配root的行, 删除root行的下一列

    [root@Shell ~]# sed '/root/{n;d}' passwd

    3.13.2 替换匹配root行的下一列

    [root@Shell ~]# sed '/root/{n; s/bin/test/}' passwd

    3.14 sed高级参数

    1. g: 将hold space中的内容拷贝到pattern space中,原来pattern space里的内容被覆盖
    2. G:将hold space中的内容append到pattern space\n后
    3. h: 将pattern space中的内容拷贝到hold space中,原来hold space里的内容被覆盖
    4. H: 将pattern space中的内容append到hold space\n后
    5. d: 删除pattern中的所有行,并读入下一新行到pattern
    6. D: 删除multiline pattern中的第一行,不读入下一行

    3.14.1 将第一行的写入到暂存区, 替换最后一行的内容

    [root@Shell ~]# sed  '1h;$g' /etc/hosts

    3.14.2 将第一行的写入到暂存区, 在最后一行调用暂存区的内容

    [root@Shell ~]# sed  '1h;$G' /etc/hosts

    3.14.3 将第一行的内容删除但保留至暂存区, 在最后一行调用暂存区内容追加至于尾部

    [root@Shell ~]# sed -r '1{h;d};$G' /etc/hosts

    3.14.4 将第一行的内容写入至暂存区, 从第二行开始进行重定向替换

    [root@Shell ~]# sed -r '1h;2,$g' /etc/hosts

    3.14.5 将第一行重定向至暂存区, 2-3行追加至暂存区, 最后追加调用暂存区的内容

    [root@Shell ~]# sed -r '1h; 2,3H; $G' /etc/hosts

    3.15 图解sed ‘1!G;h;$!d’ file

    3.15.1 sed简介

    sed是面向流的行编辑器。所谓面向流,是指接受标准输入的输入,输出内容到标准输出上。sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。

    具体过程如下: sed将处理的行读入到一个临时缓存区中(也称为模式空间pattern space),sed中的命令依次执行,直到所有命令执行完毕,完成后把该行发送到屏幕上,清理pattern space中的内容;接着重复刚才的动作,读入下一行,直到文件处理结束。

    sed每处理完一行就将其从pattern space中删除,然后将下一行读入,进行处理和显示。处理完输入 文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。

    3.15.2 sed执行流程图

    3.15.3 什么是Pattern Space,Hold Space

     Pattern Space相当于车间,sed把流内容在这里进行处理,Hold Space相当于仓库,加工的半成品在这里进行临时存储。

    由于各种原因,比如用户希望在某个条件下脚本中的某个命令被执行,或者希望模式空间得到保存以便下一次处理,都有可能使得sed在处理文件的时候不按照正常的流程来进行。这个时候,sed设置了一些高级命令来满足用户的要求。

    一些高级命令

    g: 将hold space中的内容拷贝到pattern space中,原来pattern space里的内容被覆盖

    G:将hold space中的内容append到pattern space\n后

    h: 将pattern space中的内容拷贝到hold space中,原来hold space里的内容被覆盖

    H: 将pattern space中的内容append到hold space\n后

    d: 删除pattern中的所有行,并读入下一新行到pattern中

    D: 删除multiline pattern中的第一行,不读入下一行

    3.15.4 图解sed ‘1!G;h;$!d’ file

    1. 1!G 第一行不执行G命令,从第二行开始执行
    2. $!d 最后一行不删除
    3. [root@localhost test]# cat file
    4. 1 1 1
    5. 2 2 2
    6. 3 3 3
    7.  
    8. [root@localhost test]# sed '1!G;h;$!d' file
    9. 3 3 3
    10. 2 2 2
    11. 1 1 1
    12. 图中P代表Pattern Space,H代表Hold Space。绿色代表pattern space中的数据,蓝色代表hold space中的数据。

    3.16 ​​​​​​​反向选择命令`!`

     3.16.1 除了第三行,其他全部删除

    [root@Shell ~]# sed -r '3!d' /etc/hosts

    3.17 ​​​​​​​sed匹配替换`g`

    1. s 替换命令标志
    2. g 行内全局替换
    3. i 忽略替换大小写
    4. 替换命令`s`

    3.17.1 替换每行出现的第一个root

    [root@Shell ~]# sed 's/root/alice/' passwd

    3.17.2 替换以root开头的行

    [root@Shell ~]# sed 's/^root/alice/' passwd

    3.17.3 查找匹配到的行, 在匹配的行后面添加内容

    [root@Shell ~]# sed -r 's/[0-9][0-9]$/& .5/' passwd

    3.17.4 匹配包含有root的行进行替换

    [root@Shell ~]# sed -r 's/root/alice/g' passwd

    3.17.5 匹配包含有root的行进行替换,忽略大小写

    # sed -r 's/root/alice/gi' /etc/passwd

    3.17.6 在文本的每一行开头添加空格

    [root@Shell ~]# sed -r 's/^/ /g' passwd

    3.18 后向引用(重要)

    1. [root@Shell ~]# sed -r 's#(Roo)#\1-alice#g' passwd
    2. [root@Shell ~]# ifconfig eth0|sed -n '2p'|sed -r 's#(^.*et) (.*) (net.*$)#\2#g'
    3. 示例文件内容如下:
    4. [root@lzy ~]# vim a.txt
    5. /etc/abc/456
    6. etc
    7. 删除文本中的内容,需加转义
    8. [root@Shell ~]# sed -r '\/etc\/abc\/456/d' a.txt
    9. 如果碰到/符号, 建议使用#符替换
    10. [root@Shell ~]# sed -r 's#/etc/abc/456#/dev/null#g' a.txt
    11. [root@Shell ~]# sed -r 's@/etc/abc/456@/dev/null@' a.txt

    3.19 ​​​​​​​删除文件

    3.19.1 删除配置文件中#号开头的注释行, 如果碰到tab或空格是无法删除

    [root@Shell ~]# sed '/^#/d' file

    3.19.2 删除配置文件中含有tab键的注释行

    [root@Shell ~]# sed -r '/^[ \t]*#/d' file

    3.19.3 删除无内容空行

    [root@Shell ~]# sed -r '/^[ \t]*$/d' file

    3.19.4 删除注释行及空行

    1. [root@Shell ~]# sed -r '/^[ \t]*#/d; /^[ \t]*$/d' /etc/vsftpd/vsftpd.conf
    2. [root@Shell ~]# sed -r '/^[ \t]*#|^[ \t]*$/d' /etc/vsftpd/vsftpd.conf
    3. [root@Shell ~]# sed -r '/^[ \t]*($|#)/d' /etc/vsftpd/vsftpd.conf

    3.20 ​​​​​​​给文件行添加注释

    3.20.1 将第二行到第六行加上注释信息

    [root@Shell ~]# sed '2,6s/^/#/' passwd

    3.20.2 将第二行到第六行最前面添加#注释符

    [root@Shell ~]# sed -r '2,6s/.*/#&/' passwd

    3.21 ​​​​​​​添加#注释符

    1. [root@Shell ~]# sed -r '3,$ s/^#*/#/' passwd
    2. # sed -r '30,50s/^[ \t]*#*/#/' /etc/nginx.conf
    3. # sed -r '2,8s/^[ \t#]*/#/' /etc/nginx.conf

    四、​​​​​​​Awk文本处理

    1. `awk`是一种编程语言,用于在`linux/unix`下对文本和数据进行处理。
    2. `awk`数据可以来自标准输入、一个或多个文件,或其它命令的输出。
    3. `awk`通常是配合脚本进行使用, 是一个强大的文本处理工具。

    4.1 ​​​​​​​awk 的处理数据的方式

    1. 1.进行逐行扫描文件, 从第一行到最后一行
    2. 2.寻找匹配的特定模式的行,在行上进行操作
    3. 3.如果没有指定处理动作,则把匹配的行显示到标准输出
    4. 4.如果没有指定模式,则所有被操作的行都被处理

    4.2 ​​​​​​​`awk`的语法格式

    1. awk [options] 'commands' filenames
    2. awk [options] -f awk-script-file filenames

    4.3 ​​​​​​​选项 options

    1. -F 定义输入字段分隔符,默认的分隔符, 空格或tab键
    2. 命令 command
    3. 行处理前 行处理 行处理后
    4. BEGIN{} {} END{}
    5. BEGIN发生在读文件之前
    6. [root@Shell ~]# awk 'BEGIN{print 1/2}'
    7. 0.5
    8. BEGIN在行处理前, 修改字段分隔符
    9. [root@Shell ~]# awk 'BEGIN{FS=":"} {print $1}' /etc/passwd
    10. BEGIN在行处理前, 修改字段读入和输出分隔符
    11. [root@Shell ~]# awk 'BEGIN{FS=":";OFS="---"} {print $1,$2}' /etc/passwd
    12. [root@Shell ~]# awk 'BEGIN{print 1/2} {print "ok"} END {print "Game Over"}' /etc/hosts
    13. 0.5
    14. ok
    15. ok
    16. ok
    17. Game Over

    4.4 ​​​​​​​`awk`命令格式

    4.4.1 匹配 awk 'pattern' filename

    [root@Shell ~]# awk '/root/' /etc/passwd

    4.4.2 处理动作 awk '{action}' filename

    [root@Shell ~]# awk -F: '{print $1}' /etc/passwd

    4.4.3 匹配+处理动作 awk 'pattern {action}' filename

    1. [root@Shell ~]# awk -F ':' '/root/ {print $1,$3}' /etc/passwd
    2. [root@Shell ~]# awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd

    4.4.4 判断大于多少则输出什么内容 command |awk 'pattern {action}'

    [root@Shell ~]# df |awk '/\/$/ {if ($3>50000) print $4}'

    4.5 ​​​​​​​Awk工作原理

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

    处理过程如下:

    1.awk将文件中的每一行作为输入, 并将每一行赋给内部变量`$0`, 以换行符结束

    2.awk开始进行字段分解,每个字段存储在已编号的变量中,从`$1`开始[默认空格分割]

    3.awk默认字段分隔符是由内部`FS`变量来确定, 可以使用`-F`修订

    4.awk行处理时使用了`print`函数打印分割后的字段

    5.awk在打印后的字段加上空格,因为`$1,$3` 之间有一个逗号。逗号被映射至`OFS`内部变量中,称为输出字段分隔符, `OFS`默认为空格.

    6.awk输出之后,将从文件中获取另一行,并将其存储在`$0`中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕.

    4.6 ​​​​​​​Awk内部变量

    4.6.1 `$0`保存当前记录的内容*

    [root@Shell ~]# awk '{print $0}' /etc/passwd

    4.6.2 `NR`记录输入总的编号(行号)*

    1. [root@Shell ~]# awk '{print NR,$0}' /etc/passwd
    2. [root@Shell ~]# awk 'NR<=3' /etc/passwd

    4.6.3 `FNR`当前输入文件的编号(行号)*

    1. [root@Shell ~]# awk '{print NR,$0}' /etc/passwd /etc/hosts
    2. [root@Shell ~]# awk '{print FNR,$0}' /etc/passwd /etc/hosts

    4.6.4 `NF`保存行的最后一列*

    [root@Shell ~]# awk -F ":" '{print NF,$NF}' /etc/passwd /etc/hosts

    4.6.5 `FS`指定字段分割符, 默认是空格*

    1. 以冒号作为字段分隔符
    2. [root@Shell ~]# awk -F: '/root/{print $1,$3}' /etc/passwd
    3. [root@Shell ~]# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd
    4. 以空格冒号tab作为字段分割
    5. [root@Shell ~]# awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd

    4.6.6 `OFS`指定输出字段分隔符*

    1. 逗号映射为OFS, 初始情况下OFS变量是空格
    2. [root@Shell ~]# awk -F: '/root/{print $1,$2,$3,$4}' /etc/passwd
    3. [root@Shell ~]# awk 'BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2}' /etc/passwd

    4.6.7 `RS`输入记录分隔符,默认为换行符[了解]*

    [root@Shell ~]# awk -F: 'BEGIN{RS=" "} {print $0}' /etc/hosts

    4.6.8 `ORS`将文件以空格为分割每一行合并为一行[了解]*

    [root@Shell ~]# awk -F: 'BEGIN{ORS=" "} {print $0}' /etc/hosts

    4.6.9 `print`格式化输出函数*

    1. [root@Shell ~]# date|awk '{print $2,"5月份""\n",$NF,"今年"}'
    2. [root@Shell ~]# awk -F: '{print "用户是:" $1 "\t 用户uid: " $3  "\t 用户gid:" $4}' /etc/passwd
    3. printf 函数
    4. [root@Shell ~]# awk -F: '{printf "%-15s %-10s %-15s\n", $1, $2, $3}' /etc/passwd
    5. %s 字符类型
    6. %d 数值类型
    7. 占 15 字符
    8. - 表示左对齐,默认是右对齐
    9. printf 默认不会在行尾自动换行,加\n

    4.7 ​​​​​​​Awk模式动作

    awk语句都由模式和动作组成。

    模式部分决定动作语句何时触发及触发事件。

    如果省略模式部分,动作将时刻保持执行状态。模式可以是条件语句或复合语句或正则表达式。

    4.7.1 正则表达式*

    1. 匹配记录(整行)
    2. [root@Shell ~]# awk '/^root/' /etc/passwd
    3. [root@Shell ~]# awk '$0 ~ /^root/' /etc/passwd
    4. 匹配字段:匹配操作符(~ !~)
    5. [root@Shell ~]# awk '$1~/^root/' /etc/passwd
    6. [root@Shell ~]# awk '$NF !~ /bash$/' /etc/passwd

    4.7.2 比较表达式*

    1. 比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作
    2. 比较表达式使用关系运算符,用于比较数字与字符串
    3. 关系运算符
    4. 运算符 含义 示例
    5. < 小于 x<y
    6. <= 小于或等于 x<=y
    7. == 等于 x==y
    8. != 不等于 x!=y
    9. >= 大于等于 x>=y
    10. > 大于 x>y
    11. uid为0的列出来
    12. [root@Shell ~]# awk -F ":" '$3==0' /etc/passwd
    13. uid小于10的全部列出来
    14. [root@Shell ~]# awk -F: '$3 < 10' /etc/passwd
    15. 用户登陆的shell等于/bin/bash
    16. [root@Shell ~]# awk -F: '$7 == "/bin/bash" ' /etc/passwd
    17. 第一列为alice的列出来
    18. [root@Shell ~]# awk -F: '$1 == "alice" ' /etc/passwd
    19. 为alice的用户列出来
    20. [root@Shell ~]# awk -F: '$1 ~ /alice/ ' /etc/passwd
    21. [root@Shell ~]# awk -F: '$1 !~ /alice/ ' /etc/passwd
    22. 磁盘使用率大于多少则,则打印可用的值
    23. [root@Shell ~]# df |awk '/\/$/'|awk '$3>1000000 {print $4}'

    4.7.3 条件表达式*

    1. [root@Shell ~]# awk -F: '$3>300 {print $0}' /etc/passwd
    2. [root@Shell ~]# awk -F: '{if($3>300) print $0}' /etc/passwd
    3. [root@Shell ~]# awk -F: '{if($3>5555){print $3} else {print $1}}' /etc/passwd

    4.7.4 运算表达式*

    1. [root@Shell ~]# awk -F: '$3 * 10 > 500000' /etc/passwd
    2. [root@Shell ~]# awk -F: 'BEGIN{OFS="--"} { if($3*10>50000) {print $1,$3} } END {print "打印ok"}' /etc/passwd
    3. [root@Shell ~]# awk '/southem/{print $5 + 10}' datafile
    4. [root@Shell ~]# awk '/southem/{print $5 + 10.56}' datafile
    5. [root@Shell ~]# awk '/southem/{print $8 - 10}' datafile
    6. [root@Shell ~]# awk '/southem/{print $8 / 2 }' datafile
    7. [root@Shell ~]# awk '/southem/{print $8 * 2 }' datafile
    8. [root@Shell ~]# awk '/southem/{print $8 % 2 }' datafile

    4.7.5 逻辑操作符和复合模式*

    1. &&逻辑与 || 逻辑或 !逻辑非
    2. 匹配用户名为root并且打印uid小于15的行
    3. [root@Shell ~]# awk -F: '$1~/root/ && $3<=15' /etc/passwd
    4. 匹配用户名为root或uid大于5000
    5. [root@Shell ~]# awk -F: '$1~/root/ || $3>=5000' /etc/passwd

    4.8 ​​​​​​​`awk`示例1

    1. # awk '/west/' datafile
    2. # awk '/^north/' datafile
    3. # awk '$3 ~ /^north/' datafile
    4. # awk '/^(no|so)/' datafile
    5. # awk '{print $3,$2}' datafile
    6. # awk '{print $3 $2}' datafile
    7. # awk '{print $0}' datafile
    8. # awk '{print "Number of fields: "NF}' datafile
    9. # awk '/northeast/{print $3,$2}' datafile
    10. # awk '/^[ns]/{print $1}' datafile
    11. # awk '$5 ~ /\. [7-9]+/' datafile
    12. # awk '$2 !~ /E/{print $1,$2}' datafile
    13. # awk '$3 ~ /^Joel/{print $3 "is a nice boy."}' datafile
    14. # awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile
    15. # awk '$4 ~ /Chin$/{print "The price is $" $8 "."}' datafile
    16. # awk '/Tj/{print $0}' datafile
    17. # awk -F: '{print "Number of fields: "NF}' /etc/passwd
    18. # awk -F"[ :]" '{print NF}' /etc/passwd

    4.9 ​​​​​​​`awk`示例2

    1. [root@Shell ~]# cat b.txt
    2. lzy lizhenya:is a:good boy!
    3. [root@Shell ~]# awk '{print NF}' b.txt
    4. 4
    5. [root@Shell ~]# awk -F ':' '{print NF}' b.txt
    6. 3
    7. [root@Shell ~]# awk -F"[ :]" '{print NF}' b.txt
    8. 6

    4.10 ​​​​​​​Awk条件判断

    1. if语句格式:{ if(表达式){语句;语句;... }}
    2. 打印当前管理员用户名称
    3. [root@Shell ~]# awk -F: '{ if($3==0){print $1 "is adminisitrator"} }' /etc/passwd
    4. 统计系统用户数量
    5. [root@Shell ~]# awk -F: '{ if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd
    6. 统计普通用户数量
    7. [root@Shell ~]# awk -F: '{ if($3>1000){i++}} END {print i}' /etc/passwd
    8. if...else 语句格式: {if(表达式){语句;语句;...else{语句;语句;...}}
    9. # awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd
    10. # awk -F: '{if($3==0) {count++} else{i++} }' /etc/passwd
    11. # awk -F: '{if($3==0){count++} else{i++}} END{print " 管理员个数: "count ; print " 系统用户数: "i}' /etc/passwd
    12. if...else if...else 语句格式:
    13. {if(表达式 1){语句;语句;...else if(表达式 2){语句;语句;. ..else{语句;语句;... }}
    14. [root@Shell ~]# awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print i;print j;print k}' /etc/passwd
    15. [root@Shell ~]# awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print "管理员个数"i; print "系统用户个数" j; print "系统用户个 数" }' /etc/passwd
    16. 管理员个数1
    17. 系统用户个数29
    18. 系统用户个数69

    4.11 ​​​​​​​Awk循环语句

    4.11.1 while循环

    1. [root@Shell ~]# awk 'BEGIN{ i=1; while(i<=10){print i; i++} }'
    2. [root@Shell ~]# awk -F: '{i=1; while(i<=NF){print $i; i++}}' /etc/passwd
    3. [root@Shell ~]# awk -F: '{i=1; while(i<=10) {print $0; i++}}' /etc/passwd
    4. [root@Shell ~]#cat b.txt
    5. 111 222
    6. 333 444 555
    7. 666 777 888 999
    8. [root@Shell ~]# awk '{i=1; while(i<=NF){print $i; i++}}' b.txt

    4.11.2 for循环

    1. C 风格 for
    2. [root@Shell ~]# awk 'BEGIN{for(i=1;i<=5;i++){print i} }'
    3. 将每行打印 10
    4. [root@Shell ~]# awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd
    5. [root@Shell ~]# awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' passwd

    4.12 ​​​​​​​awk数组概述

    将需要统计的某个字段作为数组的索引,然后对索引进行遍历

    4.12.1 统计`/etc/passwd`中各种类型`shell` 的数量*

    # awk -F: '{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }' /etc/passwd

    4.12.2 网站访问状态统计<当前时实状态ss>*

    [root@Shell ~]# ss -an|awk '/:80/{tcp[$2]++} END {for(i in tcp){print i,tcp[i]}}'

    4.12.3 统计当前访问的每个IP的数量<当前时实状态 netstat,ss>*

    1.4.12.3统计当前访问的每个IP的数量<当前时实状态 netstat,ss>*

    4.13 ​​​​​​​Awk数组案例

    1. `Nginx`日志分析,日志格式如下:
    2. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    3. '$status $body_bytes_sent "$http_referer" '
    4. '"$http_user_agent" "$http_x_forwarded_for"';
    5. 52.55.21.59 - - [25/Jan/2018:14:55:36 +0800] "GET /feed/ HTTP/1.1" 404 162 "https:www.google.com/" "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52" "-"

    4.13.1 统计2018年01月25日,当天的PV量*

    1. [root@Shell ~]# grep "25/Jan/2018" log.bjstack.log |wc -l
    2. [root@Shell ~]# awk "/25\/Jan\/2018/" log.bjstack.log |wc -l
    3. [root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips) {sum+=ips[i]} {print sum}}' log.bjstack.log

    4.13.2 统计15-19点的pv量

    [root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00 {print $0}"' log.bjstack.log |wc -l

    4.13.3 统计2018年01月25日,一天内访问最多的10个IP*

    [root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){ print ips[i],i}}' log.bjstack.log |sort -rn|head

    4.13.4 统计15-19点访问次数最多的10个IP

    [root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00"' log.bjstack.log |awk '{ips[$1]++} END {for(i in ips){print ips[i],i}}'|sort -rn|head

    4.13.5 统计2018年01月25日,访问大于100次的IP*

    [root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){if(ips[i]>10){print i,ips[i]}}}' log.bjstack.log

    4.13.6 统计2018年01月25日,访问最多的10个页面($request top 10)*

    [root@Shell ~]# awk '/25\/Jan\/2018/ {request[$7]++} END {for(i in request){print request[i],i}}' log.bjstack.log |sort -rn|head

    4.13.7 统计2018年01月25日,每个URL访问内容总大小($body_bytes_sent)*

    [root@Shell ~]# awk '/25\/Jan\/2018/ {request[$7]++;size[$7]+=$10} END {for(i in request){print request[i],i,size[i]}}' log.bjstack.log |sort -rn|head

    4.13.8 统计2018年01月25日,每个IP访问状态码数量($status)*

    [root@Shell ~]# awk '{ip_code[$1 " " $9]++} END {for(i in ip_code){print ip_code[i],i}}' log.bjstack.log|sort -rn|head

    4.13.9 统计2018年01月25日,访问状态码为404及出现的次数($status)*

    1. [root@Shell ~]# grep "404" log.bjstack.log |wc -l
    2. [root@Shell ~]# awk '{if($9=="404") code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log

    4.13.10 统计2018年01月25日,8:30-9:00访问状态码是404*

    1. [root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00" && $9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
    2. [root@Shell ~]# awk '$9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log

    4.13.11 统计2018年01月25日,各种状态码数量,统计状态码出现的次数

    1. [root@Shell ~]# awk '{code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
    2. [root@Shell ~]# awk '{if($9>=100 && $9<200) {i++}
    3. else if ($9>=200 && $9<300) {j++}
    4. else if ($9>=300 && $9<400) {k++}
    5. else if ($9>=400 && $9<500) {n++}
    6. else if($9>=500) {p++}}
    7. END{print i,j,k,n,p,i+j+k+n+p}' log.bjstack.log
  • 相关阅读:
    mybatis generator 表名多了个点
    计算机毕业设计 基于SpringBoot大学生创新创业项目管理系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试
    进击的Mini LED:群雄逐“屏”,谁主沉浮
    JVM 内存和 GC 算法
    数字ic设计——UART
    windows下OpenNN的编译与使用
    每天分享几个面试题(七)
    【Qt】之【项目】整理可参考学习的git项目链接(持续更新)
    Hive基础知识概念
    正则验证用户名和跨域postmessage
  • 原文地址:https://blog.csdn.net/zfw_666666/article/details/126229970