• Linux三剑客:awk的基本用法


    目录

    认识awk

    使用awk

    语法

    常用命令选项

    awk变量

    内置变量

    自定义变量

    printf命令

    格式

    演示

    操作符

    格式

    演示

    awk PATTERN 匹配部分

    格式

    演示

    awk有意思的案例


    认识awk

      awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

      awk其实不仅仅是工具软件,还是一种编程语言。不过,本文只介绍它的命令行用法,对于大多数场合,应该足够用了。

    使用awk

    语法

    awk` `[options] ``'program'` `var=value ``file````awk` `[options] -f programfile var=value ``file````awk` `[options] ``'BEGIN{ action;… } pattern{ action;… } END{ action;… }'` `file` `...

    常用命令选项

    • -F fs:fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:

    • -v var=value:赋值一个用户定义变量,将外部变量传递给awk

    • -f scripfile:从脚本文件中读取awk命令

    awk变量

    变量:内置和自定义变量,每个变量前加 -v 命令选项

    内置变量

    (1)格式

    • FS输入字段分隔符默认为空白字符

    • OFS输出字段分隔符,默认为空白字符

    • RS :输入记录分隔符,指定输入时的换行符,原换行符仍有效

    • ORS :输出记录分隔符,输出时用指定符号代替换行符

    • NF :字段数量,共有多少字段, $NF引用最后一列,$(NF-1)引用倒数第2列

    • NR行号,后可跟多个文件,第二个文件行号继续从第一个文件最后行号开始

    • FNR :各文件分别计数, 行号,后跟一个文件和NR一样,跟多个文件,第二个文件行号从1开始

    • FILENAME :当前文件名

    • ARGC :命令行参数的个数

    • ARGV :数组,保存的是命令行所给定的各参数,查看参数

    (2)演示

    1. [root@test ~]# cat awkdemo
    2. hello:world
    3. linux:redhat:lalala:hahaha
    4. test:love:youou
    5. [root@test ~]# awk -v FS=':' '{print $1,$2}' awkdemo #FS指定输入分隔符
    6. hello world
    7. linux redhat
    8. test love
    9. //这里打印了以:为输入分隔符,打印了第一列和第二列
    10. [root@test ~]# awk -v FS=':' -v OFS='---' '{print $1,$2}' awkdemo #OFS指定输出分隔符
    11. hello---world
    12. linux---redhat
    13. test---love
    14. //这里以:为输入分隔符,---为输出分隔符,然后打印出了第一列和第二类
    15. [root@test ~]# awk -v RS=':' '{print $1,$2}' awkdemo
    16. hello
    17. world linux
    18. redhat
    19. lalala test
    20. love
    21. youou
    22. //指定以:为换行符,并且原换行符无效
    23. [root@test ~]# awk -v FS=':' -v ORS='---' '{print $1,$2}' awkdemo
    24. hello world---linux redhat---test love---
    25. //这里以:为输入分隔符,并且将‘---’替换\n 来输出第一列和第二列
    26. [root@test ~]# awk -F: '{print NF}' awkdemo
    27. 2
    28. 4
    29. 3
    30. //打印出了每行的字段数
    31. [root@test ~]# awk -F: '{print $(NF-1)}' awkdemo #显示倒数第2列
    32. hello
    33. lalala
    34. love
    35. //显示出倒数第二列
    36. [root@test ~]# awk '{print NR}' awkdemo awkdemo1
    37. 1
    38. 2
    39. 3
    40. 4
    41. 5
    42. //打印出行号
    43. [root@test ~]# awk END'{print NR}' awkdemo awkdemo1
    44. 5
    45. //打印出最后一行的行号
    46. [root@test ~]# awk '{print FNR}' awkdemo awkdemo1
    47. 1
    48. 2
    49. 3
    50. 1
    51. 2
    52. //一共两个文件,各文件分别计数, 行号,
    53. [root@test ~]# awk '{print FILENAME}' awkdemo
    54. awkdemo
    55. awkdemo
    56. awkdemo
    57. //当前文件名
    58. [root@test ~]# awk 'BEGIN {print ARGC}' awkdemo awkdemo1
    59. 3
    60. //命令行参数的个数
    61. [root@test ~]# awk 'BEGIN {print ARGV[0]}' awkdemo awkdemo1
    62. awk
    63. //第一个参数
    64. [root@test ~]# awk 'BEGIN {print ARGV[1]}' awkdemo awkdemo1
    65. awkdemo
    66. //第二个参数
    67. [root@test ~]# awk 'BEGIN {print ARGV[2]}' awkdemo awkdemo1
    68. awkdemo1
    69. //第三个参数

    自定义变量

    自定义变量( 区分字符大小写)

    (1)-v var=value

    ① 先定义变量,后执行动作print

    1. [root@centos111 test]# awk -v name="yps" -F: '{print name":"$0}' awkdemo
    2. yps:hello:world
    3. yps:linux:redhat:lalala:hahaha
    4. yps:along:love:youou

    ② 在执行动作print后定义变量

    1. [root@centos111 test]# awk -F: '{print name":"$0;name="yps"}' awkdemo
    2. :hello:world
    3. yps:linux:redhat:lalala:hahaha
    4. yps:along:love:youou

    (2)在program 中直接定义

    可以把执行的动作放在脚本中,直接调用脚本 -f

    1. [root@centos111 test]# cat awk
    2. {name="yps";print name,$1}
    3. [root@centos111 test]# awk -F: -f awk awkdemo
    4. yps hello
    5. yps linux
    6. yps along

    printf命令

    比print更强大

    格式

    (1)格式化输出

    printf` `"FORMAT"``, item1,item2, ...

    ① 必须指定FORMAT

    不会自动换行,需要显式给出换行控制符,\n

    ③ FORMAT 中需要分别为后面每个item 指定格式符

    (2)格式符:与item 一一对应

    • %c: 显示字符的ASCII码

    • %d, %i: 显示十进制整数

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

    • %f :显示为浮点数,小数 %5.1f,带整数、小数点、整数共5位,小数1位,不够用空格补上

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

    • %s :显示字符串;例:%5s最少5个字符,不够用空格补上,超过5个还继续显示

    • %u :无符号整数

    • %%: 显示% 自身

    (3)修饰符:放在%c[/d/e/f...]之间

    • #[.#]:第一个数字控制显示的宽度;第二个# 表示小数点后精度,%5.1f

    • -:左对齐(默认右对齐) %-15s

    • +:显示数值的正负符号 %+d

    演示

    1. ---筛选出/etc/passwd文件中的第一列个第三列
    2. [root@centos111 test]# awk -F: '{print $1,$3}' /etc/passwd | grep root
    3. root 0
    4. ---第一列显示小于5的字符串;第2列显示整数并换行
    5. [root@centos111 test]# awk -F: '{printf "%5s--%u\n",$1,$3}' /etc/passwd
    6. root--0
    7. bin--1
    8. daemon--2
    9. ...
    10. ---使用-进行左对齐;第2列显示浮点数
    11. [root@centos111 test]# awk -F: '{printf "%-20s--%-10.3f\n",$1,$3}' /etc/passwd
    12. root --0.000
    13. bin --1.000
    14. daemon --2.000
    15. ...

    操作符

    格式

    • 算术操作符

      • x+y, x-y, x*y, x/y, x^y, x%y

      • -x: 转换为负数

      • +x: 转换为数值

    • 字符串操作符:没有符号的操作符,字符串连接

    • 赋值操作符:

      • =, +=, -=, *=, /=, %=, ^=

      • ++, --

    • 比较操作符:

      • ==, !=, >, >=, <, <=

    • 逻辑操作符:与&& ,或|| ,非!

    • 函数调用: function_name(argu1, argu2, ...)

    • 条件表达式(三目表达式):

      selector ? if-true-expression : if-false-expression

      • 注释:先判断selector,如果符合执行 ? 后的操作;否则执行 : 后的操作

    演示

    (1)模式匹配符

    1. ---查询以/dev开头的磁盘信息
    2. [root@centos111 test]# df -h | awk '/^\/dev/'
    3. /dev/mapper/centos-root 17G 9.5G 7.6G 56% /
    4. /dev/sda1 1014M 254M 761M 25% /boot
    5. ---只显示磁盘使用状况和磁盘名
    6. [root@centos111 test]# df -h | awk '/^\/dev/{print$(NF-1)"--"$1}'
    7. 56%--/dev/mapper/centos-root
    8. 25%--/dev/sda1
    9. ---查找磁盘大于40%的
    10. [root@centos111 test]# df -h | awk '$0 ~ /^\/dev/{print$(NF-1)"--"$1}' | awk -F% '$1 > 40'
    11. 56%--/dev/mapper/centos-root

    (2)逻辑操作符

    1. [root@centos111 test]# awk -F: '$3>=0&&$3<=1000{print $1,$3}' /etc/passwd
    2. root 0
    3. bin 1
    4. daemon 2
    5. ...
    6. [root@centos111 test]# awk -F: '$3==0||$3>=1000{print $1}' /etc/passwd
    7. root
    8. nfsnobody
    9. user
    10. user1
    11. user2
    12. [root@centos111 test]# awk -F: '!($3==0){print $1}' /etc/passwd
    13. bin
    14. ...
    15. [root@centos111 test]# awk -F: '!(/bash$/){print $1,$3}' /etc/passwd
    16. bin 1
    17. daemon 2
    18. ...

    (3)条件表达式(三目表达式)

    1. [root@centos111 test]# awk -F: '{$3>=1000? usertype="common user":usertypr="sysadmin user";print usertype,$1,$3}' /etc/passwd
    2. root 0
    3. bin 1
    4. ...
    5. common user nfsnobody 65534
    6. common user gnome-initial-setup 989
    7. ...

    awk PATTERN 匹配部分

    格式

    PATTERN:根据pattern 条件,过滤匹配的行,再做处理

    (1)如果未指定:空模式,匹配每一行

    (2)/regular expression/ :仅处理能够模式匹配到的行,正则,需要用/ / 括起来

    (3)relational expression:关系表达式,结果为“真”才会被处理

    真:结果为非0值,非空字符串

    假:结果为空字符串或0值

    (4)line ranges:行范围

      startline(起始行),endline(结束行):/pat1/,/pat2/ 不支持直接给出数字,可以有多段,中间可以有间隔

    (5)BEGIN/END 模式

      BEGIN{}: 仅在开始处理文件中的文本之前执行一次

      END{} :仅在文本处理完成之后执行

    演示

    1. [root@centos111 test]# awk -F: '{print $1}' awkdemo
    2. hello
    3. linux
    4. along
    5. [root@centos111 test]# awk -F: '/hello/{print $1}' awkdemo
    6. hello
    7. [root@centos111 test]# awk -F: '1{print $1}' awkdemo
    8. hello
    9. linux
    10. along
    11. [root@centos111 test]# awk -F: '0{print $1}' awkdemo
    12. [root@centos111 test]# awk -F: '/^h/,/^a/{print $1}' awkdemo
    13. hello
    14. linux
    15. along
    16. [root@centos111 test]# awk -F: 'BEGIN{print "第一列"}{print $1} END{print "结束"}' awkdemo
    17. 第一列
    18. hello
    19. linux
    20. along
    21. 结束

    awk有意思的案例

    "seq 10" 是一个 Linux 命令,表示生成一个从 1 到 10 的序列。

    1. [root@centos111 test]# seq 10
    2. 1
    3. 2
    4. 3
    5. 4
    6. 5
    7. 6
    8. 7
    9. 8
    10. 9
    11. 10

    ---因为i=0,为假,所以不打印

    [root@centos111 test]# seq 10 | awk 'i=0'

    ---i=1,为真,所以全部打印

    1. [root@centos111 test]# seq 10 | awk 'i=1'
    2. 1
    3. 2
    4. 3
    5. 4
    6. 5
    7. 6
    8. 7
    9. 8
    10. 9
    11. 10

    ---只打印奇数行;奇数行i进入时本身为空,被赋为!i,即不为空,所以打印;偶数行i进入时本身不为空,被赋为!i,即为空,所以不打印

    1. [root@centos111 test]# seq 10 | awk 'i=!i'
    2. 1
    3. 3
    4. 5
    5. 7
    6. 9

    ---解释上一个操作,i在奇偶行的值

    1. [root@centos111 test]# seq 10 | awk '{i=!i;print i}'
    2. 1
    3. 0
    4. 1
    5. 0
    6. 1
    7. 0
    8. 1
    9. 0
    10. 1
    11. 0

    ---只打印偶数行,是上边打印奇数行的取反

    1. [root@centos111 test]# seq 10 | awk '!(i=!i)'
    2. 2
    3. 4
    4. 6
    5. 8
    6. 10

    ---只打印偶数行;先对i进行赋值,即不为空,刚好和打印奇数行相反

    1. [root@along ~]# seq 10 |awk -v i=1 'i=!i'
    2. 2
    3. 4
    4. 6
    5. 8
    6. 10

    seq 100 |awk 'i=!i'
    那这段是怎么理解?
    首先我们要了解一下awk对于未定义的变量处理方法:
    对于数值运算,未定义变量的话awk会赋予变量初值为0
    对于字符运算,未定义变量的话awk会赋予变量初值为空字符串
    了解了这两条我们再看awk 'i=!i'这条命令是什么含义,awk是对文本文件一行一行处理的,seq 100命令执行后是如下形式:
    1

    2

    3

    ……

    100
    首相它读取第一行数据,也就是1,然后进行模式匹配,i是一个未定义的变量,上面我们提到了对于数值运算,未定义变量的话初值会为0,这时i的值即为0,也就是i=!0,那么!是什么呢?!就是取反的意思,等号右边其实就是个布尔值,0为假,1为真,这里是!0,那么它就为非假,也就是为真,真的值为1,因此i=!0(1)也就相当于i=1,到此i的值为1.

    i的值为1后有什么作用呢?
    i=1说明值为真,awk会认定模式为真,这时匹配是成功的,会把第一行输出到屏幕,可能有的人会问了这里只有i=!i,没有print,它怎么输出的?awk的格式为 模式{ 动作},如果只有模式没有动作,那么匹配成功后默认的会输出整条记录,也就是说这条命令完整的写法为:
    seq 1 100 | awk 'i=!i{print $0}'
    为什么第二行没有输出呢?
    前面进行第一行模式匹配的时候i的值已经由0变为了1,在进行第二行操作的时候,i=!i变成了i=!1,这样i的值就又变成了0(假),所以第二行没有输出,到了处理第三行的时候,i=!i变成了i=!0,所以会输出第三行,以此类推……这样我们就可以输出奇数行而删除偶数行了。
    那么如何输出偶数行呢?
    我们可以加一个if判断一下,如果i的值为真我们就输出奇数行,如果为假就输出偶数行

    1. [root@centos111 test]# seq 1 10 |awk '{i=!i;if(i) print $0}'
    2. 1
    3. 3
    4. 5
    5. 7
    6. 9
    7. [root@centos111 test]# seq 1 10 |awk '{i=!i;if(!i) print $0}'
    8. 2
    9. 4
    10. 6
    11. 8
    12. 10

    看到这儿又有朋友可能会问了,为什么现在把i=!i放到动作里了呢?
    我们看这两条命令:

    1. [root@centos111 test]# seq 1 10 |awk 'i=!i{print !i}'
    2. 0
    3. 0
    4. 0
    5. 0
    6. 0
    7. [root@centos111 test]# seq 1 10 |awk 'i=!i{print i}'
    8. 1
    9. 1
    10. 1
    11. 1
    12. 1

    如果把i=!i放到模式里边它会进行匹配,把匹配的结果传递给动作,那个时候已经把不匹配的舍去了,所以我们无法用if来判断i的值。

    到这里awk的一些基本用法就结束了,下一篇会继续介绍awk的高级用法

  • 相关阅读:
    手写实现简易Spring框架
    java开发IP 属地功能
    玄子Share-揭开5G神秘面纱
    arcgis地形分析全流程
    初学Nodejs(2):Buffer缓冲区
    大前端CPU优化技术--SIMD技术
    八大排序详解
    图解LSTM VS GRU
    Pycharm和Jupyter的对比
    【计算机毕业设计论文_软件测试_商业进销存管理系统】测试报告【自动化测试】【功能测试】
  • 原文地址:https://blog.csdn.net/qq_68163788/article/details/134458325