awk技能
awk技巧
awk默认就是空格和TAB,如果要指定用TAB可以用 awk -F '\t' 如果要指定多个TAB当作一个处理,可以用 awk -F '\t+' *********************** 1.基本完整用法 *********************** ---1.基本完整用法 last -n 5 |awk '!/^$/' | awk 'BEGIN {print "username,IP" } {print $1,$3} \ END {print "最后登录的用户和ip地址"}' ---2.查看最后登录的五个用户和ip地址并去掉空行 last -n 5 |awk '!/^$/' | awk 'BEGIN {print "username,IP" } {print $1,$3} \ END {print "最后登录的用户和ip地址"}' --首选 last -n 5 |awk 'BEGIN {print "username,IP" } !/^$/ {print $1,$3} \ END {print "最后登录的用户和ip地址"}' *********************** ----2.AWK循环 *********************** ---2.1 显示所有用户名 awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; \ END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd ---2.2循环显示目录名 find /etc/sysconfig/network-scripts/ -name "ifcfg-*" |awk -F "/" ' {print $5}' >test.txt cat test.txt ifcfg-em1 ifcfg-em2 ifcfg-lo ifcfg-em1 ifcfg-em2 ifcfg-lo ifcfg-em1 ifcfg-em2 ifcfg-lo ifcfg-08 ifcfg-10 ifcfg-l1 --#带行号显示(数组) awk 'BEGIN {count=0;} {name[count] = $1;count++;}; \ END{for (i = 0; i < NR; i++) print i, name[i]}' /root/test.txt ---结果为: 0 ifcfg-em1 1 ifcfg-em2 2 ifcfg-lo 3 ifcfg-em1 4 ifcfg-em2 5 ifcfg-lo 6 ifcfg-em1 7 ifcfg-em2 8 ifcfg-lo 9 ifcfg-08 10 ifcfg-10 11 ifcfg-l1 --#不带行号显示 # awk '{for(i=1;i<=NF;i++) {printf $i" "} printf "\n"}' /root/test.txt ifcfg-em1 ifcfg-em2 ifcfg-lo ifcfg-em1 ifcfg-em2 ifcfg-lo ifcfg-em1 ifcfg-em2 ifcfg-lo ifcfg-08 ifcfg-10 ifcfg-l1 df -H |awk -F '\t' '{ print $1,$2,$3,$4,$5,$6}' *********************** 3.awk模糊 *********************** --3.1模糊匹配: 查询第四列中是否含有Brown $awk '{if($4~/Brown/) print $0}' grade.txt 如果在文本中查询字符串"Brown",使用/Brown/ 和 $awk '$4~/Brown/' grade.txt 作用相同。 --3.2模糊不匹配 $ awk '$0 !~ /Brown/' grade.txt $ awk '{if($4 !~ /Brown/) print $0' grade.txt --3.3匹配字符或字符串 # awk -F: '$1~/me/' passwd games:x:12:100:games:/usr/games:/sbin/nologin # awk -F: '$1~/user/' passwd user1:x:600:501::/home/user1:/bin/bash 可以让某个段去匹配,~ 表示匹配的意思,以冒号分隔第一字段然后匹配//里的关键字; 1 2 3 4 5 6 # awk -F: '/root/ {print $1,$3} /user/ {print $1,$3}' passwd root 0 operator 11 ftp 14 saslauth 499 user1 600 awk还可以多次匹配 *********************** 4.精确匹配 *********************** $ awk '$3 == "48" {print $0}' grade.txt $ awk '{if ($3=="48") print $0}' grade.txt # awk -F: '$3=="0"' passwd root:x:0:0:root:/root:/bin/bash # awk -F: '$3==10' passwd uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin 判断第3个字段为10的并且打印该行的第7字段; 1 2 3 4 # awk -F: '$3==10 {print $7}' passwd /sbin/nologin # awk -F: '$3=="600"' passwd user1:x:600:501::/home/user1:/bin/bash awk中是可以用逻辑符号判断的,比如 ‘==’ 就是等于,也可以理解为 ‘精确匹配’ 另外也有 >, ‘>=, ‘<, ‘<=, ‘!= 等等,值得注意的是,在和数字比较时,若把比较的数字用双引号引起来后,那么awk不会认为是数字,而认为是字符,不加双引号则认为是数字。 示例,双引号括起来认为是字符;加单引号和不加则认为是数字; # awk -F: '$3>"500"' passwd | sort -t: -k 3 -n 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 vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin sshd:x:74:74:privilege-separated ssh:/var/empty/sshd:/sbin/nologin dbus:x:81:81:system message bus:/:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin nobody:x:99:99:nobody:/:/sbin/nologin user1:x:600:501::/home/user1:/bin/bash # awk -F: '$3>500' passwd | sort -t: -k 3 -n user1:x:600:501::/home/user1:/bin/bash # awk -F: '$3>'500'' passwd | sort -t: -k 3 -n user1:x:600:501::/home/user1:/bin/bash *********************** 5.精确不匹配 *********************** $awk '$4!="brwon" {print $0}' grade.txt # awk -F: '$7!="/sbin/nologin"' passwd 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 user1:x:600:501::/home/user1:/bin/bash mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash # awk -F: '$3>"5" && $3<"7"' passwd shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin user1:x:600:501::/home/user1:/bin/bash 另外还可以使用 && “并且”和 || “或者” 的意思。 示例,打印第3段大于第4段,并且第7段为/bin/bash的行; # awk -F: '$3>$4 && $7=="/bin/bash"' passwd user1:x:600:501::/home/user1:/bin/bash NOTE:尖角符号代表行首,“.”代表任意字符。 *********************** 6.统计功能 *********************** netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' NOTE: ^ 是开头的意思,就是说开头是TCP字样的,$NF表示最后一个字段,把它放入数组S中,然后自加. END最后用for取出数组中的下标,也就是TCP的几种状态,然后对应该下标的值,就是统计的数量. 理解如下: 观察一、先输出两个值,其中NF为awk正在处理记录(行)的字段总数,$NF为每行最后一个字段的值 # netstat -na |awk '/^tcp/ {print NF,$NF}' 6 LISTEN 6 LISTEN 6 LISTEN 6 LISTEN 6 LISTEN 6 LISTEN 6 LISTEN 6 LISTEN 6 LISTEN 6 LISTEN 6 TIME_WAIT 6 TIME_WAIT 6 TIME_WAIT 6 TIME_WAIT 6 ESTABLISHED 6 ESTABLISHED 6 ESTABLISHED 6 ESTABLISHED 6 ESTABLISHED 6 TIME_WAIT 6 TIME_WAIT 6 LISTEN 6 LISTEN 6 ESTABLISHED 观察二、如下命令输出4个值,注意前后俩字段的值是怎么来的。。。S[LISTEN], ++S[LISTEN] # netstat -na |awk '/^tcp/ {print NF,$NF,S[$NF],++S[$NF]}' 6 LISTEN 1 6 LISTEN 1 2 6 LISTEN 2 3 6 LISTEN 3 4 6 LISTEN 4 5 6 LISTEN 5 6 6 LISTEN 6 7 6 LISTEN 7 8 6 LISTEN 8 9 6 LISTEN 9 10 6 TIME_WAIT 1 6 ESTABLISHED 1 6 TIME_WAIT 1 2 6 TIME_WAIT 2 3 6 TIME_WAIT 3 4 6 ESTABLISHED 1 2 6 ESTABLISHED 2 3 6 ESTABLISHED 3 4 6 ESTABLISHED 4 5 6 LISTEN 10 11 6 LISTEN 11 12 6 ESTABLISHED 5 6 观察三、利用awk的行处理特性,遍历了所有tcp开头的行。 定义出不同状态命名的数组下标,并分别++计数赋值给数组元素, 最后打印$NF和数组S[$NF]的值。观察粗体部分 # netstat -na | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' TIME_WAIT 4 ESTABLISHED 6 LISTEN 12 SYN_RECV表示正在等待处理的请求数; ESTABLISHED表示正常数据传输状态; TIME_WAIT表示处理完毕,等待超时结束的请求数。 *********************** 7.awk小技巧 *********************** 第一行: NR==1 或 !i++ 第n行: NR==n 最后一行: 0 或 "" 或 1==0 或 1>2 ,总之任一个假值就可以 匹配正则表达式RE的行: /RE/ --7.1取指定行 --7.2从第二行开始打印 awk 'FNR>1 { print $1}' a.txt awk 'NR==2,NR==0 { print $1}' a.txt --7.3取中间几行 awk '{if(NR>=302&&NR<=379)$0="#"$0}1' sphinx.conf --7.4打印每行,并删除第二列 awk '{$2="";print }' test.txt --7.5打印部分文本,即输出所有行,但是第一、二列为空 awk '{ $1 = "";$3 = ""; print }' test1 --7.6打印文件中除第一列和第三列外的其它列、同时从第二行开始打印 awk 'BEGIN{print "ocpyang"} FNR>1 { $1 = "";$3 = ""; print }' test.txt --7.7打印文件中除第一列和第三列外的其它列以及第一行第二行 awk ' NR==1,NR==2 { $1 = "";$3 = ""; print }' test.txt --7.8文本间隔: # 每行后面增加一行空行 awk '1;{print ""}' awk 'BEGIN{ORS="\n\n"};1' # 每行后面增加两行空行 awk '1;{print "\n"}' --7.9每句行前加上编号 awk '{print FNR "\t" $0}' test.txt 其中,0为显示所有列;亦可用1,2来显示1,2列 --7.10用制表符 (\t) 给所有文件加上连贯的编号 awk '{print NR "\t" $0}' test.txt ---7.11去除#开始的行同时删除空行 awk '!/^#/ && !/^$/ ' wsrep.cnf