2022
我们一起努力

Linux系统使用awk格式化输出文本

AWK 是由 Alfred Aho,Peter Weinberger, 和 Brian Kernighan一起创造的一种处理文本文件的语言,是一个强大的文本分析工具。下面良许教程网为大家详细讲解一下Linux系统中使用awk格式化输出文本。

Linux系统使用awk格式化输出文本

AWK简介:

awk是Unix环境下一种非常好的语言,适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行特殊技巧程序设计。对于短消息来说,比如处理话单文件,使用awk就非常方便,鉴于测试组大部分人对awk并不熟悉,因此仅以本文作一个提纲挈领的介绍,希望对初学者迅速掌握awk有所帮助。

语法

1 语法

一个典型的awk语法如下:

 awk '{
 
      BEGIN{stat1}
      BEGIN{stat2}
      pattern1{action1}
      pattern2{action2}
      ...
      patternn{actionn}
      {默认动作,无条件,始终执行}
 
      END{stat1}
      END{stat2}
 }'

其中BEGIN为处理文本前的操作,一般用于改变FS,OFS,RS,ORS等,BEGIN部分完成之后,awk读取第一行输入,并将第一行的数据填入1,$2,NR,NF等变量,然后进入正式处理阶段,待所有行处理完毕之后,进入END部分,END一般用于总结,打印报表等。正式处理是一个内建的循环,每一次循环读取一行数据,每一行的处理分为多模式,多动作,文本行符合条件pattern1就执行动作action1符合pattern2就执行动作action2…,还可以有默认的动作, 即没有pattern判断,始终执行此{}内的action。

BEGIN,END部分不是必须出现,可以没有,也可以有任意多个

pattern部分的写法有:

  • /reg/: 在整行范围内匹配reg,匹配到就执行后续动作

  • ! /reg/: 整行没匹配到reg,才执行后续动作

  • $1 ~ /reg/:只在第一字段匹配reg

  • $1 !~ /reg/: 不匹配

  • NR>=2: 从第二行开始处理

pattern,部分和随后的if,for部分,能用到的符号有:

2 内建变量

 $0
 当前记录(这个变量中存放着整个行的内容)
 $1~$n
 当前记录的第n个字段,字段间由FS分隔
 FS
 输入字段分隔符 默认是空格或\t
 NF
 当前记录中的字段个数,就是有多少列
 NR
 已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
 FNR
 当前记录数,与NR不同的是,这个值会是各个文件自己的行号
 RS
 输入的记录分隔符, 默认为换行符
 OFS
 输出字段分隔符, 默认也是空格
 ORS
 输出的记录分隔符,默认为换行符
 FILENAME
 当前输入文件的名字

3 if,for语句

#在任何时候{}内都可以跟多个并列动作(使用“;”分隔),下面的{action1} 和 {action1;action2;…} 都表示{}体内有多个动作,两种表示没有任何区别,写第二种仅仅是为了直观的表示可以有多个动作

#for循环写法

 for(i=1;i

#if 判断写法

 if($1 ~ /reg/){action1}; else if($1 ~ /reg2/){action2}; else{action3} #else if部分可以没有
 if($1 ~ /reg/ && $2 ~ /reg2/){action} #多个条件用”&&”,”||”表示
 if($1 ~ /reg/ || NR >= 5){action

# if,for 混合写法

 { for(i=1;i

for循环的作用范围为:

  • 其后紧跟的if; else if; else语句

  • 其后紧跟的{}中的多个动作

  • 其后紧跟的一个第一个普通动作

if语句的作用范围:

  • if后紧跟的第一个动作

  • if后紧跟的{}中的多个动作

4 awk技巧

1: AWK使用的RE为ERE

2: 如果在BEGIN中设置了OFS, 只有$0有改动OFS才能生效

3: printf 与 print 的区别: printf 不自动打印换行符, print 则自动打印

4: gsub的返回值并不是替换后的字符串,而是返回替换的次数

5: 字符串常量一定在用” “包围起来,否则当作变量使用, 如 $1==”ipaddress”

6: AWK 的 for 循环为 C-Style,即为 for(), 区别于shell中的for i in …

7: AWK中可以使用多个分隔符,要封装在方括号里,用’ ‘包围,以防 shell 对它们进行解释,如 awk -F ‘[ :/t]’ ,使用空格,冒号,tab作为分隔符

8: next语句:从输入文件中取得下一个输入行,在AWK命令表顶部重新执行命令,一般用于跳过一些特殊的行

9: awk 匹配多个条件: awk ‘/kobe/ && /james/’ #匹配同时有kobe和james的行

10: FS的默认值是[ /t/n]+, OFS的默认值为空格,RS,ORS的默认值都是换行

11: 定位行有两种方法: 1: NR==行号 2: 用RE /Love$/

12: exit语句:终止AWK程序,但不跳过END语句

13:n表示第几列(字段),$0表示整个行.

14:awk可用比较运算符:!=, >, =,

15: 字符串匹配:~: 匹配 !~: 不匹配

16: &&:多个条件且, || 多个条件或

17: {s1;s2;s3;…}中多个语句用分号隔开;if; else if; else

18: print 后不带任何参数时,相当于print $0 ,将会打印整行记录

awk字符函数

函数 说明
gsub( Ere, Repl, [ In ] ) 除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行,。
sub( Ere, Repl, [ In ] ) 用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由 Ere 参数指定的扩展正则表达式的第一个具体值。sub 函数返回替换的数量。出现在 Repl 参数指定的字符串中的 &(和符号)由 In 参数指定的与 Ere 参数的指定的扩展正则表达式匹配的字符串替换。如果未指定 In 参数,缺省值是整个记录($0 记录变量)。
index( String1, String2 ) 在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,返回位置,从 1 开始编号。如果 String2 参数不在 String1 参数中出现,则返回 0(零)。
length [(String)] 返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。
blength [(String)] 返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。
substr( String, M, [ N ] ) 返回具有 N 参数指定的字符数量子串。子串从 String 参数指定的字符串取得,其字符以 M 参数指定的位置开始。M 参数指定为将 String 参数中的第一个字符作为编号 1。如果未指定 N 参数,则子串的长度将是 M 参数指定的位置到 String 参数的末尾 的长度。
match( String, Ere ) 在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从 1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH 特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。
split( String, A, [Ere] ) 将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],并返回 n 变量的值。此分隔可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符(FS 特殊变量)来进行(如果没有给出 Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。
tolower( String ) 返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。
toupper( String ) 返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。
sprintf(Format, Expr, Expr, . . . ) 根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。
以上函数转自:linux awk 内置函数详细介绍(实例)

awk 实例

1.awk作用域
 awk '/AL/ {printf $1; print $2}' emp.txt
 awk '/AL/{print $1} {print $2}' emp.txt

1.第一种只处理匹配到AL的行; 然后打印这些行的第一字段和第二字段

2.第二种只有在匹配到AL的行才打印字段一,但是字段二是无条件的,始终打印

2.awk内置函数用法

如下文本test.log,需要把文本中单位是”M”的字段转换为”G”

 16G   16G   1.9G   40G none
 4G     4G     952M   60G
 16G   16G   1.6G   40G none
 5G     780M   5G     80G

若我们单纯地想替换字符串,则可以使用一下命令,注意:print没带默认参数时,默认打印整行记录

 cat 1.txt | awk '{
   sub(/M/,"G",$i)
   print
 }'

完整替换如下,替换的同时进行数值计算

 cat 1.log | \
 awk '{
    for(i=1;i

1.使用for遍历每一行的每一个字段,使用if处理匹配到”M”的字段,然后调用awk内置函数int, substr, match处理, 关于awk内置函数,可以参考linux awk 内置函数详细介绍(实例)

2.先乘100,再除以100,是为了转换为”G”单位后保留两位小数

3.注意 printf,print 两个函数的区别

3.awk条件语句

如第二个例子中的文本,现在需要分别统计每行中带有”G”, “M”, “none” 字段的个数,并输出

 cat test.log | \
 awk '
      BEGIN{OFS="\t"}
      {    
        a=b=c=0
        for(i=1;i

结果如下:

 16G   16G   1.9G   40G   G:4   M:0   none:0
 4G     4G     952M   60G   G:3   M:1   none:0
 16G   16G   1.6G   40G   G:4   M:0   none:0
 5G     780M   5G     80G   G:3   M:1   none:0
 end!
4.awk中break用法

给出一个如下文本test2.log,在每一行中,只输出字母及其之前的字符

 1 2 a 5 6
 11 b 55 66
 21 22 23 c 25 26

写法如下:

 cat test2.log | \
 awk '{
    for(i=1;i

1.break 用法跟c语言用法一样,跳出for循环

5.awk中数组

如下文本test3.log,给定一个id值,输出其在所有id中是第几个

 test1id=615187629
 test2test3id=615183434
 test4id=615123789
 test5id=615975882

给定id值615123789,其在所有id中是第三个,计算如下:

 cat test3.log | \
 awk -v var1=615123789 -F [=] '
    /id/ {
        b+=1
        a[b]=$2
    }
    END {
        for(i in a) if(a[i] == var1) print "number:",i
    }
 '

6.awk中的整数计算

如下文本,这是一个kvm虚拟机进程(省略了部分文本),我们要获取其映射到宿主机上的vnc端口号,即由”-vnc 0.0.0.0:1″字符串计算出其vnc端口号为5901(5900 + 1),若是”-vnc 0.0.0.0:2″,则端口号为5902

 cat kvm.txt
 qemu 144148 4.7 4.2 ... /usr/local/qemu/bin/qemu-kvm -name lnmptest-107 ... -device isa-serial,chardev=charserial0,id=serial0 -vnc 0.0.0.0:1 -vga cirrus timestamp=on

实现有多种,sed,shell,awk都可以

 #awk
 cat kvm.txt | awk '{ for(i=1;i

以上就是良许教程网为各位朋友分享的Linux系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你!

137e00002230ad9f26e78-265x300

本文来源:www.lxlinux.net/1690.html,若引用不当,请联系修改。

赞(0)
文章名称:《Linux系统使用awk格式化输出文本》
文章链接:https://www.fzvps.com/154593.html
本站文章来源于互联网,如有侵权,请联系管理删除,本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
图片版权归属各自创作者所有,图片水印出于防止被无耻之徒盗取劳动成果的目的。

评论 抢沙发

评论前必须登录!