Linux文本处理三剑客之awk

目录:

  1. #查看系统环境 
  2. !lsb_release -a 

输出:

  1. No LSB modules are available. 
  2. Distributor ID: LinuxMint 
  3. Description: Linux Mint 19.3 Tricia 
  4. Release: 19.3 
  5. Codename: tricia 

  1. #查看文本内容 
  2. !cat awk_text 

输出:

  1. 1 M.Tansley 05/99 48311 Green 8 40 44 
  2. 2 J.Lulu 06/99 48317 green 9 24 26 
  3. 3 P.Bunny,02/99,48,Yellow,12,35,28 
  4. 4 J.Troll:07/99:4842:Brown-3:12:26:26 
  5. 5 L.Tansley:05/99:4712:Brown-2:12:30:28 

注意:jupyter运行linux指令需要在指令前加!

命令格式

awk 命令的基本格式为:

  1. awk 'BEGIN{ 命令1 } 模式{ 命令2 } END{ 命令3 }' 文件 

awk工作流程
awk工作流程

  • 1、BEGIN 执行 BEGIN 块的内容,即命令1内容,可选。
  • 2、完成 BEGIN 块的执行,开始执行body块。
  • 3、读入有 \n 换行符分割的记录。
  • 4、将记录按指定的域分隔符划分域,填充域。
  • 5、依次执行各 BODY 块,pattern 部分匹配该行内容成功后,才会执行命令2的内容。
  • 6、循环读取并执行各行直到文件结束,完成body块执行。
  • 7、开始 END 块执行,命令3内容,END 块可以输出最终结果,可选。

选用参数

选项 含义
-F fs 指定以 fs 作为输入行的分隔符,awk 命令默认分隔符为空格或制表符。
-f file 从脚本文件中读取 awk 脚本指令,以取代直接在命令行中输入指令。
-v var=val 在执行处理过程之前,设置一个变量 var,并给其设备初始值为 val。

awk 命令的脚本命令:

  1. '匹配规则{执行命令}' 

1.匹配规则:可以使用字符串(比如 /demo/,表示查看含有 demo 字符串的行)或者正则表达式指定

2.执行命令:需要用大括号({})括起来

注意:

  • 整个脚本命令是用单引号('')括起
  • 在 awk 程序执行时,如果没有指定执行命令,则默认会把匹配的行输出;如果不指定匹配规则,则默认匹配文本中所有的行。

awk 命令的运行方式:

  • 1.awk命令行: #awk
  • 2.awk程序文件: #awk -f /data/awk_script//将swk命令写到文件中,然后调用这个文件
  • 3.awk脚本: #!/bin/awk -f

详细使用

指定分隔符

  1. !awk -F: '{print $1}' awk_text 
  2. print('--------------------------------------------------------------')  
  3. !awk -F: '{print $1}' awk_text 

输出:

  1. 1 M.Tansley 05/99 48311 Green 8 40 44 
  2. 2 J.Lulu 06/99 48317 green 9 24 26 
  3. 3 P.Bunny,02/99,48,Yellow,12,35,28 
  4. 4 J.Troll 
  5. 5 L.Tansley 
  6. -------------------------------------------------------------- 
  7. 1 M.Tansley 05/99 48311 Green 8 40 44 
  8. 2 J.Lulu 06/99 48317 green 9 24 26 
  9. 3 P.Bunny,02/99,48,Yellow,12,35,28 
  10. 4 J.Troll 
  11. 5 L.Tansley 

从文件中读取程序

跟 sed 一样,awk 允许将脚本命令存储到文件中,然后再在命令行中引用

  1. !cat awk.sh 

输出:

  1. {print "The fifth number after" $1 "is" $6} 

  1. !awk -f awk.sh awk_text 

输出:

  1. The fifth number after1is8 
  2. The fifth number after2is9 
  3. The fifth number after3is 
  4. The fifth number after4is 
  5. The fifth number after5is 

  1. !cat awk.func 

输出:

  1. #!/bin/awk -f 
  2. #运行前 
  3. BEGIN { 
  4. math = 0 
  5. english = 0 
  6. computer = 0 
  7. printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n" 
  8. printf "---------------------------------------------\n" 
  9. } 
  10. #运行中 
  11. { 
  12. math+=$3 
  13. english+=$4 
  14. computer+=$5 
  15. printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5 
  16. } 
  17. #运行后 
  18. END { 
  19. printf "---------------------------------------------\n" 
  20. printf " TOTAL:%10d %8d %8d \n", math, english, computer 
  21. printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR 
  22. } 

  1. !awk -f awk.func score 

输出:

  1. NAME NO. MATH ENGLISH COMPUTER TOTAL 
  2. --------------------------------------------- 
  3. Marry 2143 78 84 77 239 
  4. Jack 2321 66 78 45 189 
  5. Tom 2122 48 77 71 196 
  6. Mike 2537 87 97 95 279 
  7. Bob 2415 40 57 62 159 
  8. --------------------------------------------- 
  9. TOTAL: 319 393 350  
  10. AVERAGE: 63.80 78.60 70.00 

设置变量

  1. !awk -v a=1 '{print NR,$2,$2+a}' awk_text 

输出:

  1. 1 M.Tansley 1 
  2. 2 J.Lulu 1 
  3. 3 P.Bunny,02/99,48,Yellow,12,35,28 1 
  4. 4 J.Troll:07/99:4842:Brown-3:12:26:26 1 
  5. 5 L.Tansley:05/99:4712:Brown-2:12:30:28 1 

内建变量

序号 变量 描述
1 $n 当前记录的第n个字段,字段间由FS分隔
2 $0 完整的输入记录
3 ARGC 命令行参数的数目
4 ARGIND 命令行中当前文件的位置(从0开始算)
5 ARGV 包含命令行参数的数组
6 CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
7 ERRNO 最后一个系统错误的描述
8 FIELDWIDTHS 字段宽度列表(用空格键分隔)
9 FILENAME 当前文件名
10 FNR 各文件分别计数的行号
11 FS 字段分隔符(默认是任何空格)
12 IGNORECASE 如果为真,则进行忽略大小写的匹配
13 NF 一条记录的字段的数目
14 NR 已经读出的记录数,就是行号,从1开始
15 OFMT 数字的输出格式(默认值是%.6g)
16 OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
17 ORS 输出记录分隔符(默认值是一个换行符)
18 RLENGTH 由match函数所匹配的字符串的长度
19 RS 记录分隔符(默认是一个换行符)
20 RSTART 由match函数所匹配的字符串的第一个位置
21 SUBSEP 数组下标分隔符(默认值是/034)

数据字段变量

awk 会自动给一行中的每个数据元素分配一个变量

变量 含义
$0 代表整个文本行;
$1 代表文本行中的第 1 个数据字段;
$2 代表文本行中的第 2 个数据字段;
$n 代表文本行中的第 n 个数据字段。

注意:在 awk 中,默认的字段分隔符是任意的空白字符(例如空格或制表符),awk 在读取一行文本时,会用预定义的字段分隔符划分每个数据字段

  1. # 查看全部 
  2. !awk '{print $0}' awk_text 
  3. print('--------------------------------------------------------') 
  4. # 查看每一行的第一个内容 
  5. !awk '{print $1}' awk_text 
  6. print('--------------------------------------------------------') 
  7. # 查看每一行的最后一个内容 
  8. !awk '{print $6}' awk_text 

输出:

  1. 1 M.Tansley 05/99 48311 Green 8 40 44 
  2. 2 J.Lulu 06/99 48317 green 9 24 26 
  3. 3 P.Bunny,02/99,48,Yellow,12,35,28 
  4. 4 J.Troll:07/99:4842:Brown-3:12:26:26 
  5. 5 L.Tansley:05/99:4712:Brown-2:12:30:28 
  6. -------------------------------------------------------- 
  7. 1 
  8. 2 
  9. 3 
  10. 4 
  11. 5 
  12. -------------------------------------------------------- 
  13. 8 
  14. 9 

其他参数

  1. !awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' awk_text 

输出:

  1. FILENAME ARGC FNR FS NF NR OFS ORS RS 
  2. --------------------------------------------- 
  3. awk_text 2 1 8 1  
  4. awk_text 2 2 8 2  
  5. awk_text 2 3 2 3  
  6. awk_text 2 4 2 4  
  7. awk_text 2 5 2 5  

  1. !awk 'BEGIN{FS="[ :]+"}{print $1,$2}' awk_text 

输出:

  1. 1 M.Tansley 
  2. 2 J.Lulu 
  3. 3 P.Bunny,02/99,48,Yellow,12,35,28 
  4. 4 J.Troll 
  5. 5 L.Tansley 

多个命令

awk 允许将多条命令组合成一个正常的程序。要在命令行上的程序脚本中使用多条命令,只要在命令之间放个分号即可

  1. !echo "My name is Tom" | awk '{$4="ann";print $0}' 

输出:

  1. My name is ann 

BEGIN关键字与END关键字

  1. !awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }' 

输出:

  1. 1 
  2. 2 
  3. 3 
  4. 4 
  5. 5 

printf指定输出格式

printf "FORMAT" ,item1,item2,…//指格式化输出,必须指定FORMAT,不会自动换行,换行使用换行符\n;FORMAT中需要为每个item指定格式符:与item--对应

%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%: 显示%自身

修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
-: 左对齐(默认右对齐) %-15s
+:显示数值的正负符号 %+d

  1. !awk 'BEGIN {printf "%s %s %-4.2f\n","TOM","man",66.1234}' 
  2. !awk 'BEGIN {printf "%-10s %-8s %-4.2f\n","TOM","man",66.1234}' 

输出:

  1. TOM man 66.12 
  2. TOM man 66.12 

操作符

  • 算数操作符 : x+y, x-y,x*y, x/y, x^y, x%y;-x: 转换为负数 ;+x: 转换为数值
  • 赋值操作符 : =, +=, -=, *=, /=, %=, ^= ++, --
  • 比较操作符:==, !=, >, >=, <, <=
  • 模式匹配符:~:左边是否和右边匹配包含 !~:是否不匹配
  • 逻辑操作符:与&&,或||,非!
  • 条件表达式(三目表达式):
  1. !echo "1.7 2.52" | awk '{printf ("%2f\n",$1)}' 
  2. !echo "1.7 2.52" | awk '{printf ("%d\n",$2)}' 

输出:

  1. 1.700000 
  2. 2 

分支语句

  1. !awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d 是偶数\n", num }' 
  2. !awk 'BEGIN {num = 11; if (num % 2 == 0) printf "%d 是偶数\n", num; else printf "%d 是奇数\n", num }' 

输出:

  1. 10 是偶数 
  2. 11 是奇数 

循环语句

  1. print('For----------------------------------------------') 
  2. !awk 'BEGIN { for (i = 1; i <= 2; ++i) print i }' 
  3. print('While----------------------------------------------') 
  4. !awk 'BEGIN {i = 1; while (i < 3) { print i; ++i } }' 
  5. print('Break----------------------------------------------') 
  6. !awk 'BEGIN {sum = 0; for (i = 0; i < 10; ++i) {sum += i; if (sum > 15) break; else print "Sum =", sum }}' 
  7. print('Continue----------------------------------------------') 
  8. !awk 'BEGIN {for (i = 1; i <= 10; ++i) {if (i % 2 == 0) print i; else continue;}}' 
  9. print('Exit----------------------------------------------') 
  10. !awk 'BEGIN {sum = 0; for (i = 0; i < 10; ++i) {sum += i; if (sum > 15) exit(10); else print "Sum =", sum }}' 

输出:

  1. For---------------------------------------------- 
  2. 1 
  3. 2 
  4. While---------------------------------------------- 
  5. 1 
  6. 2 
  7. Break---------------------------------------------- 
  8. Sum = 0 
  9. Sum = 1 
  10. Sum = 3 
  11. Sum = 6 
  12. Sum = 10 
  13. Sum = 15 
  14. Continue---------------------------------------------- 
  15. 2 
  16. 4 
  17. 6 
  18. 8 
  19. 10 
  20. Exit---------------------------------------------- 
  21. Sum = 0 
  22. Sum = 1 
  23. Sum = 3 
  24. Sum = 6 
  25. Sum = 10 
  26. Sum = 15 

数组

语法格式:

  1. array_name[index]=value 

  1. !awk 'BEGIN {sites["runoob"]="www.runoob.com";sites["google"]="www.google.com";print sites["runoob"] "\n" sites["google"]}' 

输出:

  1. www.runoob.com 
  2. www.google.com 

函数

自定义函数

语法格式:

  1. function function_name(argument1, argument2, ...) 
  2. { 
  3. function body 
  4. } 

注意:

  • 1.function_name 是用户自定义函数的名称。函数名称应该以字母开头,其后可以是数字、字母或下划线的自由组合。AWK 保留的关键字不能作为用户自定义函数的名称。
  • 2.自定义函数可以接受多个输入参数,这些参数之间通过逗号分隔。参数并不是必须的。我们也可以定义没有任何输入参数的函数。
  • 3.function body 是函数体部分,它包含 AWK 程序代码。
  1. !cat awk.func2 
  1. # 返回最小值 
  2. function find_min(num1, num2) 
  3. { 
  4. if (num1 < num2) 
  5. return num1 
  6. return num2 
  7. } 
  8.  
  9. # 返回最大值 
  10. function find_max(num1, num2) 
  11. { 
  12. if (num1 > num2) 
  13. return num1 
  14. return num2 
  15. } 
  16.  
  17. # 主函数 
  18. function main(num1, num2) 
  19. { 
  20. # 查找最小值 
  21. result = find_min(10, 20) 
  22. print "Minimum =", result 
  23.  
  24. # 查找最大值 
  25. result = find_max(10, 20) 
  26. print "Maximum =", result 
  27. } 
  28.  
  29. # 脚本从这里开始执行 
  30. BEGIN { 
  31. main(10, 20) 
  32. }  

  1. !awk -f awk.func2 

输出:

  1. Minimum = 10 
  2. Maximum = 20 

内置函数

  1. !awk 'BEGIN {param = 5; result = exp(param); printf "The exponential value of %f is %f.\n", param, result;}' 
  2. print('------------------------------------------') 
  3. !awk 'BEGIN {str = "Hello, World";print "String before replacement = " str;sub("World", "Jerry", str);print "String after replacement = " str}' 
  4. print('------------------------------------------') 
  5. !awk 'BEGIN{info="this is a test2012test!";print index(info,"11111")?"ok":"no found";}' 

输出:

  1. The exponential value of 5.000000 is 148.413159. 
  2. ------------------------------------------ 
  3. String before replacement = Hello, World 
  4. String after replacement = Hello, Jerry 
  5. ------------------------------------------ 
  6. no found 

实例列举

  1. #从文件中找出长度大于10的行 
  2. !awk 'length>38' awk_text 

输出:

  1. 1 M.Tansley 05/99 48311 Green 8 40 44 
  2. 2 J.Lulu 06/99 48317 green 9 24 26 
  3. 5 L.Tansley:05/99:4712:Brown-2:12:30:28 

  1. #打印Hello world 
  2. !awk 'BEGIN { print "Hello, world!" }' 

输出:

  1. Hello, world! 

  1. #9*9乘法表 
  2. !seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}' 

输出:

  1. 1x1=1 
  2. 1x2=2 2x2=4 
  3. 1x3=3 2x3=6 3x3=9 
  4. 1x4=4 2x4=8 3x4=12 4x4=16 
  5. 1x5=5 2x5=10 3x5=15 4x5=20 5x5=25 
  6. 1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36 
  7. 1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49 
  8. 1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64 
  9. 1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81 
posted @ 2020-05-14 11:02  好奇不止,探索不息  阅读(316)  评论(0编辑  收藏  举报