本文针对linux中的文本处理“三剑客”之一的awk命令进行使用解释,awk对以行为单位对文本数据进行处理
输出:
1 2 3 4 5 No LSB modules are available. Distributor ID: LinuxMint Description: Linux Mint 19.3 Tricia Release: 19.3 Codename: tricia
输出:
1 2 3 4 5 1 M.Tansley 05/99 48311 Green 8 40 44 2 J.Lulu 06/99 48317 green 9 24 26 3 P.Bunny,02/99,48,Yellow,12,35,28 4 J.Troll:07/99:4842:Brown-3:12:26:26 5 L.Tansley:05/99:4712:Brown-2:12:30:28
注意:jupyter运行linux指令需要在指令前加!
命令格式awk 命令的基本格式为:
1 awk 'BEGIN{ 命令1 } 模式{ 命令2 } END{ 命令3 }' 文件
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.匹配规则:可以使用字符串(比如 /demo/,表示查看含有 demo 字符串的行)或者正则表达式指定
2.执行命令:需要用大括号({})括起来
注意:
整个脚本命令是用单引号(‘’)括起 在 awk 程序执行时,如果没有指定执行命令,则默认会把匹配的行输出;如果不指定匹配规则,则默认匹配文本中所有的行。 awk 命令的运行方式:
awk 命令行: # awk awk 程序文件: # awk -f /data/awk_script//将 swk 命令写到文件中,然后调用这个文件 3.awk脚本: #!/bin/awk -f 详细使用 指定分隔符1 2 3 !awk -F: '{print $1}' awk_text print ('--------------------------------------------------------------' ) !awk -F: '{print $1}' awk_text
输出:
1 2 3 4 5 6 7 8 9 10 11 1 M.Tansley 05/99 48311 Green 8 40 44 2 J.Lulu 06/99 48317 green 9 24 26 3 P.Bunny,02/99,48,Yellow,12,35,28 4 J.Troll 5 L.Tansley -------------------------------------------------------------- 1 M.Tansley 05/99 48311 Green 8 40 44 2 J.Lulu 06/99 48317 green 9 24 26 3 P.Bunny,02/99,48,Yellow,12,35,28 4 J.Troll 5 L.Tansley
从文件中读取程序跟 sed 一样,awk 允许将脚本命令存储到文件中,然后再在命令行中引用
输出:
1 {print "The fifth number after" $1 "is" $6}
输出:
1 2 3 4 5 The fifth number after1is8 The fifth number after2is9 The fifth number after3is The fifth number after4is The fifth number after5is
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # !/bin/awk -f # 运行前 BEGIN { math = 0 english = 0 computer = 0 printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n" printf "---------------------------------------------\n" } # 运行中 { math+=$3 english+=$4 computer+=$5 printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5 } # 运行后 END { printf "---------------------------------------------\n" printf " TOTAL:%10d %8d %8d \n", math, english, computer printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR }
输出:
1 2 3 4 5 6 7 8 9 10 NAME NO. MATH ENGLISH COMPUTER TOTAL --------------------------------------------- Marry 2143 78 84 77 239 Jack 2321 66 78 45 189 Tom 2122 48 77 71 196 Mike 2537 87 97 95 279 Bob 2415 40 57 62 159 --------------------------------------------- TOTAL: 319 393 350 AVERAGE: 63.80 78.60 70.00
设置变量1 !awk -v a=1 '{print NR,$2,$2+a}' awk_text
输出:
1 2 3 4 5 1 M.Tansley 1 2 J.Lulu 1 3 P.Bunny,02/99,48,Yellow,12,35,28 1 4 J.Troll:07/99:4842:Brown-3:12:26:26 1 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 3 4 5 6 7 8 !awk '{print $0}' awk_text print ('--------------------------------------------------------' )!awk '{print $1}' awk_text print ('--------------------------------------------------------' )!awk '{print $6}' awk_text
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 M.Tansley 05/99 48311 Green 8 40 44 2 J.Lulu 06/99 48317 green 9 24 26 3 P.Bunny,02/99,48,Yellow,12,35,28 4 J.Troll:07/99:4842:Brown-3:12:26:26 5 L.Tansley:05/99:4712:Brown-2:12:30:28 -------------------------------------------------------- 1 2 3 4 5 -------------------------------------------------------- 8 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 2 3 4 5 6 7 FILENAME ARGC FNR FS NF NR OFS ORS RS --------------------------------------------- awk_text 2 1 8 1 awk_text 2 2 8 2 awk_text 2 3 2 3 awk_text 2 4 2 4 awk_text 2 5 2 5
1 !awk 'BEGIN{FS="[ :]+"}{print $1,$2}' awk_text
输出:
1 2 3 4 5 1 M.Tansley 2 J.Lulu 3 P.Bunny,02/99,48,Yellow,12,35,28 4 J.Troll 5 L.Tansley
多个命令awk 允许将多条命令组合成一个正常的程序。要在命令行上的程序脚本中使用多条命令,只要在命令之间放个分号
即可
1 !echo "My name is Tom" | awk '{$4="ann";print $0}'
输出:
BEGIN关键字与END关键字1 !awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
输出:
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 2 !awk 'BEGIN {printf "%s %s %-4.2f\n","TOM","man",66.1234}' !awk 'BEGIN {printf "%-10s %-8s %-4.2f\n","TOM","man",66.1234}'
输出:
1 2 TOM man 66.12 TOM man 66.12
操作符算数操作符 : x+y, x-y,x*y, x/y, x^y, x%y;-x: 转换为负数 ;+x: 转换为数值 赋值操作符 : =, +=, -=, *=, /=, %=, ^= ++, – 比较操作符:==, !=, >, >=, <, <= 模式匹配符:~:左边是否和右边匹配包含 !~:是否不匹配 逻辑操作符:与&&,或||,非! 条件表达式(三目表达式): 1 2 !echo "1.7 2.52" | awk '{printf ("%2f\n",$1)}' !echo "1.7 2.52" | awk '{printf ("%d\n",$2)}'
输出:
分支语句1 2 !awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d 是偶数\n", num }' !awk 'BEGIN {num = 11; if (num % 2 == 0) printf "%d 是偶数\n", num; else printf "%d 是奇数\n", num }'
输出:
循环语句1 2 3 4 5 6 7 8 9 10 print ('For----------------------------------------------' )!awk 'BEGIN { for (i = 1; i <= 2; ++i) print i }' print ('While----------------------------------------------' )!awk 'BEGIN {i = 1; while (i < 3) { print i; ++i } }' print ('Break----------------------------------------------' )!awk 'BEGIN {sum = 0; for (i = 0; i < 10; ++i) {sum += i; if (sum > 15) break; else print "Sum =", sum }}' print ('Continue----------------------------------------------' )!awk 'BEGIN {for (i = 1; i <= 10; ++i) {if (i % 2 == 0) print i; else continue;}}' print ('Exit----------------------------------------------' )!awk 'BEGIN {sum = 0; for (i = 0; i < 10; ++i) {sum += i; if (sum > 15) exit(10); else print "Sum =", sum }}'
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 For---------------------------------------------- 1 2 While---------------------------------------------- 1 2 Break---------------------------------------------- Sum = 0 Sum = 1 Sum = 3 Sum = 6 Sum = 10 Sum = 15 Continue---------------------------------------------- 2 4 6 8 10 Exit---------------------------------------------- Sum = 0 Sum = 1 Sum = 3 Sum = 6 Sum = 10 Sum = 15
数组语法格式:
1 !awk 'BEGIN {sites["runoob"]="www.runoob.com";sites["google"]="www.google.com";print sites["runoob"] "\n" sites["google"]}'
输出:
1 2 www.runoob.com www.google.com
函数 自定义函数语法格式:
1 2 3 4 function function_name(argument1, argument2, ...){ function body }
注意:
1.function_name 是用户自定义函数的名称。函数名称应该以字母开头,其后可以是数字、字母或下划线的自由组合。AWK 保留的关键字不能作为用户自定义函数的名称。 2.自定义函数可以接受多个输入参数,这些参数之间通过逗号分隔。参数并不是必须的。我们也可以定义没有任何输入参数的函数。 3.function body 是函数体部分,它包含 AWK 程序代码。 # 返回最小值
function find_min(num1, num2)
{
if (num1 < num2)
return num1
return num2
}
# 返回最大值
function find_max(num1, num2)
{
if (num1 > num2)
return num1
return num2
}
# 主函数
function main(num1, num2)
{
# 查找最小值
result = find_min(10, 20)
print "Minimum =", result
# 查找最大值
result = find_max(10, 20)
print "Maximum =", result
}
# 脚本从这里开始执行
BEGIN {
main(10, 20)
}
输出:
1 2 Minimum = 10 Maximum = 20
内置函数1 2 3 4 5 !awk 'BEGIN {param = 5; result = exp(param); printf "The exponential value of %f is %f.\n", param, result;}' print ('------------------------------------------' )!awk 'BEGIN {str = "Hello, World";print "String before replacement = " str;sub("World", "Jerry", str);print "String after replacement = " str}' print ('------------------------------------------' )!awk 'BEGIN{info="this is a test2012test!";print index(info,"11111")?"ok":"no found";}'
输出:
1 2 3 4 5 6 The exponential value of 5.000000 is 148.413159. ------------------------------------------ String before replacement = Hello, World String after replacement = Hello, Jerry ------------------------------------------ no found
实例列举1 2 !awk 'length>38' awk_text
输出:
1 2 3 1 M.Tansley 05/99 48311 Green 8 40 44 2 J.Lulu 06/99 48317 green 9 24 26 5 L.Tansley:05/99:4712:Brown-2:12:30:28
1 2 !awk 'BEGIN { print "Hello, world!" }'
输出:
1 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 2 3 4 5 6 7 8 9 1x1=1 1x2=2 2x2=4 1x3=3 2x3=6 3x3=9 1x4=4 2x4=8 3x4=12 4x4=16 1x5=5 2x5=10 3x5=15 4x5=20 5x5=25 1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36 1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49 1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64 1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81