六周第三次课(1月17日) 9.6/9.7 awk

建立测试环境

[root@localhost ~]# cp /etc/passwd awk/test.txt
[root@localhost ~]# awk -F ':' '{print $1}' test.txt
[root@localhost ~]# cd awk
[root@localhost awk]# 

[root@localhost awk]# awk -F ':' '{print $1}' test.txt

  1. 示例命令中,-F是制定分隔符,print为打印动作,用来打印某个字段,$1为第1个字段,$2为第2个字段,以此类推,但$0比较特殊,它表示整行:

mark mark

  1. -F 后面紧跟单引号,单引号内制定分隔符,print的动作要用{}括起来,可以自定义内容,但内容要加双引号。

mark

3.匹配字符或者字符串 示例命令:

[root@localhost awk]# awk '/oo/' test.txt
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
setroubleshoot:x:991:986::/var/lib/setroubleshoot:/sbin/nologin

这和sed的用法想死,实现grep功能,没有颜色显示,这里还可以匹配某一段,这里~就是匹配的意思

[root@localhost awk]# awk -F ':' '$1 ~/oo/' test.txt
root:x:0:0:root:/root:/bin/bash
setroubleshoot:x:991:986::/var/lib/setroubleshoot:/sbin/nologin

4.awk支持特殊字符+等,且不必和grep那样+E,sed +r mark

  1. awk支持多个表达式,下例中awk匹配玩root,再匹配test,它还可以只打印所匹配的段。
[root@localhost awk]# awk -F ':' '/root/ {print $1,$2} /test/ {print $1,$3}' test.txt
root x
operator x
test 1002
  1. 条件操作符
  • awk中是可以用逻辑符号判断的,比如 ‘==’ 就是等于,也可以理解为 ‘精确匹配’ 另外也有 >, ‘>=, ‘<, ‘<=, ‘!= 等等,值得注意的是,在和数字比较时,若把比较的数字用双引号引起来后,那么awk不会认为是数字,而认为是字符,不加双引号则认为是数字。 示例:
[root@localhost awk]# awk -F ':' '$3>=1000 {print $0}' test.txt
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash

mark

  • 这里1000和“1000”的区别,“1000”是字符串,按照ASCII码来比较大小,这就和sort排序是一样的了
ASCII比较大小的时候,是比较两个数中的第一个字符 
1)常用字符有128个,编码从0到127。 
2)控制字符:0~31、127,共33个,不可显示; 
3)普通字符:95个,包括10个阿拉伯数字、52个英文大小写字母、33个运算符。 
4)每个字符占一个字节,7位,最高位为0。 
常见ASCII码的大小规则,0-9<A-Z<a-z: 
1)数字比字母要小。如 “7”<“F” 
2)数字0比数字9要小,并按0到9顺序递增。如 “3”<“8” 
3)字母A比字母Z要小,并按A到Z顺序递增。如“A”<“Z” 
4)同个字母的大写字母比小写字母要小32。如“A”<“a” 
记住几个常见字母的ASCII码大小: 
“A”为65;“a”为97;“0”为48;
  • != 为不匹配,除了针对某一个段的字符进行逻辑比较外,还可以两个段之间进行逻辑比较:
[root@localhost awk]# awk -F ':' '$7!="/sbin/nologin" {print $0}' test.txt
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash
  • $3<$4,$3==$4等进行比较
[root@localhost awk]# awk -F ':' '$3<$4' test.txt
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
  • 还可以使用&&和||,表示并且和或者,以及~匹配。
[root@localhost awk]# awk -F ':' '$3>"5"&& $4<"7"' test.txt
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@localhost awk]# awk -F ':' '$3>1000 || $7~"/bash"' test.txt
root:x:0:0:root:/root:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash
[root@localhost awk]# awk -F ':' '$3>1000 || $7 ~/bash/' test.txt
root:x:0:0:root:/root:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash 

7 awk的内置变量

  • awk常用的变量有:OSF、NF和NR。OFS与-F选项功能类似,用来定义分隔符,但是它是用在输出时候定义。NF表示用分隔符分隔后一共多少行,NR表示行号。

mark

  • 嵌套if语句
[root@localhost awk]# awk -F ':' '{OFS="#"} {if ($3>1000) {print $1,$2,$3,$4}}' /etc/passwd
nfsnobody#x#65534#65534
xavidsf#x#1001#1001
test#x#1002#1002
Ding#x#1003#1003

* NR表示行号,NF表示多少段

  • [ ] #awk -F ':' '{print NR":"$0}' test.txt
  • [ ] awk -F ':' '{print NF}' test.txt

mark mark

  • NR还可以作为判断条件,显示10行;

mark

  • NR配合段匹配一个使用,NR也是同理使用
[root@localhost awk]# awk -F ':' 'NR<=10 && $1 ~ /root|sync/' test.txt
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync

8 awk 的数学运算

  • =与==的区别,一个是赋值,即更改某些段的数值或字符,==是一个是判断

mark

  • 没有冒号,可以在OFS中定义
[root@localhost awk]# head -n 3 test.txt |awk -F ':' '{OFS=":"} $1="root"'
root:x:0:0:root:/root:/bin/bash
root:x:1:1:bin:/bin:/sbin/nologin
root:x:2:2:daemon:/sbin:/sbin/nologin
  • awk对各段的值进行数学运算,示例如下:
[root@localhost awk]# head -n 3 test.txt |awk -F ':' '{$7=$3+$4;print $0}'
root x 0 0 root /root 0
bin x 1 1 bin /bin 2
daemon x 2 2 daemon /sbin 4
  • awk计算某个段的总和,这里的END要注意一下,表示所有的行都已经执行,这是awk特有的语法,其实awk连同sed都可以写成一个脚本文件,而且有他们特有的语法,在awk中使用if判断、for循环都是可以的。
[root@localhost awk]# awk -F ':' '{(tot=tot+$3)}; END {print tot}' /etc/passwd
82235