9.6/9.7 awk






awk awk相对于sed 更方便的功能是支持了分段。

image.png

awk不会更改文件的内容


最简单的一种用法,以某种分隔符来分割后,取第几部分打印出来。

awk -F ':' '{print $1}' passwd

-F 分隔符  {$1 第一部分}

{$1,$2,$3} 第一二三部分

{$0表示所有段} awk '{print $0}' passwd

image.png


如果希望分段出来的结果之间有一个分隔显示,可以这样

awk -F ":" '{print $1" "$2" "$3}' passwd 这个就是以:为分隔符,找出第一二三位,中间用空格隔开,当然空格也可以为其他符号

image.png

image.png


awk的匹配功能,类似sed的功能

匹配出有oo的段

awk '/oo/' passwd

image.png

在这个基础上,如果想查看第几个段的,可以加上$位置~ 来匹配。比如像查看第一个段落中是否有oo的

awk -F ':' '$1~ /oo/' passwd 这个场景使用在比如想在passwd查找某一个用户是否存在 因为第一个冒号前面是用户名

image.png


awk可以支持多个表达式一起写,比如我们想查找含有root的第一位和第三位以及第一位可能有lo的所在行。

表达式要写在一对单引号内,print的内容要用{}


使用场景: 

awk -F ':' '/root/ {print $1,$3} $1~/lo+/ {print $0}' passwd  

image.png

operator 11 是啥玩意?其实这个就是passwd里的内容

image.png

使用awk 和grep同时来展示如何选出包含root 和 user的行

image.png


接下来的用法可以理解为一个简易的数学运算表达

可以理解为这样:以某种分隔符分割开后的每一部分进行比较, == >= != 

eg awk -F ':' '$1== "root"' passwd  分割后的第一部分是否为root

image.png


eg awk -F ':' '$3 >=1000' passwd 打印出第三部分大于等于1000的

image.png

注意这个被比较的是1000这个数字。如果把1000用双引号引起来的话,就代表是字符串,也就是按照1000的ANSCII码值。默认如果是字符串比较的话,必须使用双引号

如果不写print的范围,默认的是全部 $0

image.png

image.png     


image.png

从上面的例子可以看出,其实awk可以理解为简单的小程序,包括了算数运算,逻辑运算的等。,可以随心所欲的加各种判断条件只要是符合awk的格式      

awk -F ':' '$3<$4 {print $3,$4}' passwd 比较第三个第四位并打印出第三和第四位

image.png


image.png

如果想部分匹配该怎么做? 使用匹配符 ~ 。

可以使用或 || 与 &&来进行条件的选择或者同时满足。

eg 我想匹配第三位小于第四位同时第一位的首字符是在a-h的范围内

awk -F ':' '$3<$4 && $1 ~"^[a-h]"' passwd  匹配符~ 记得用双引号引起来条件

image.png


OFS内置变量是用来指定print时候用的分隔符。几个注意的地方:

  1. OFS要在大括号里进行定义

2. OFS要写在条件的前面


image.png

eg  awk -F ':' '{OFS="*****"} $3>1000 || $7~ /bash/ {print $1,$3,$7}' passwd


image.png


NR NF这两个内置变量

NR代表有多少行  NF代表有多少列

image.png


image.png


甚至可以加判断条件 if 

image.png


image.png 


也可以将行号加在前面

awk -F ':' '{print NF ":" $0}' passwd

image.png


打印前十行,同时打印行号

awk -F ':' 'NR <=10 {print NR "-"$0}' passwd

image.png


awk -F ':' '{print $NR":" $NF }' passwd

这个相当于 $1:$7 $2:$7 ------$行数:$7


image.png


接下来的这个,注意== 和 =的区别,同时可以看看 OFS的用法

image.png



tot是total的变量 求和.注意语法。 注意!!!tot不是内置变量。和OFS 不一样。在这里这个变量可以用任何数代替。

awk -F ':' '{tot=tot+$4}; END {print tot}' passwd 所有第四段的和,简单的求和运算。

image.png


还有就是加上判断,if后进行显示。

image.png



总结一下

awk我认为是三种里最简单的,因为它具备了一定编程语言的特点,所以写起来比较顺手。

注意一些变量,语法以及双引号和单引号的用法。


课后练习:

  1. 用awk 打印整个test.txt (以下操作都是用awk工具实现,针对test.txt)

  2. 查找所有包含 ‘bash’ 的行

  3. 用 ‘:’ 作为分隔符,查找第三段等于0的行

  4. 用 ‘:’ 作为分隔符,查找第一段为 ‘root’ 的行,并把该段的 ‘root’ 换成 ‘toor’ (可以连同sed一起使用)

  5. 用 ‘:’ 作为分隔符,打印最后一段

  6. 打印行数大于20的所有行

  7. 用 ‘:’ 作为分隔符,打印所有第三段小于第四段的行

  8. 用 ‘:’ 作为分隔符,打印第一段以及最后一段,并且中间用 ‘@’ 连接 (例如,第一行应该是这样的形式 'root@/bin/bash‘ )

  9. 用 ‘:’ 作为分隔符,把整个文档的第四段相加,求和

老师答案:

1. awk '{print $0}' test.txt
2. awk '/bash/' test.txt
3. awk -F':' '$3=="0"' test.txt
4. awk -F':' '$1=="root"' test.txt |sed 's/root/toor/'
5. awk -F':' '{print $NF}' test.txt
6. awk -F':' 'NR>20' test.txt
7. awk -F':' '$3<$4' test.txt
8. awk -F':' '{print $1"@"$NF}' test.txt
9. awk -F':' '{(sum+=$4)}; END {print sum}' test.txt



我的操作答案:

  1.  awk '$0' passwd

  2.  awk '/bash/' passwd 记住关键字是在//中间

  3.  awk -F ':' '$3==0' passwd

  4.  awk -F ':' '/root/' passwd | sed 's/root/toor/g'  有两点需要注意 第一是sed 第一个关键字前面有个s 第二个是sed后面不需要再跟passwd了

  5.  awk -F ':' '{print $NF}' passwd    注意NR 和 NF 区别

  6.  awk -F ':' '{if(NR>20) {print $0}}' passwd

  7.  awk -F ':' '$3<$4 {print $0}' passwd

  8.  awk -F ':' '{OFS="@"} {print $1,$NF}' passwd 老师的做法更简单一些。

  9.  awk -F ':' '{(tot=tot+$4)}; END {print tot}' passwd 看了老师的做法才知道tot不是默认的。。。