文件处理命令:awk

awk擅长于对数据进行分析并生成报告,简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

使用方法:
awk '{pattern +action}' {filenames}

[root@limt01 ~]# cat /etc/passwd|awk -F: '{ print $1 }'

root

bin

daemon

adm

lp

sync

。。。

其中 -F:为指定分隔符为:

 

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

1 指定分隔符

[root@limt01 tmp]# awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd

root 0 /root

bin 1 /bin

daemon 2 /sbin

adm 3 /var/adm

lp 4 /var/spool/lpd

sync 5 /sbin

shutdown 6 /sbin

halt 7 /sbin

mail 8 /var/spool/mail

operator 11 /root

games 12 /usr/games

ftp 14 /var/ftp

。。。

2 指定输出分隔符(OFS="\t")

[root@limt01 tmp]# awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd

root    0       /root

bin     1       /bin

daemon  2       /sbin

adm     3       /var/adm

lp      4       /var/spool/lpd

sync    5       /sbin

shutdown        6       /sbin

halt    7       /sbin

mail    8       /var/spool/mail

operator        11      /root

games   12      /usr/games

ftp     14      /var/ftp

。。。

3 条件过滤输出

[root@limt01 tmp]# awk -F: '{ if( $1 ~ /root/ || $1 ~ /limt/) { print $1,$3,$6 } }' OFS="\t" /etc/passwd

root    0       /root

limt    1000    /home/limt
[root@limt01 tmp]# awk -F: '$1 ~ /root/ || $1 ~ /limt/  { print $1,$3,$6  }' OFS="\t" /etc/passwd

root    0       /root

limt    1000    /home/limt

4 重定向输出到指定文件

[root@limt01 tmp]# awk 'NR!=1{print $0 > "/tmp/passwd" }' /etc/passwd

[root@limt01 tmp]# 

[root@limt01 tmp]# ls -lrt /tmp|tail

总用量 12

-rw-------. 1 root root    0 5月  20 21:36 yum.log

drwxr-xr-x. 2 root root   17 5月  20 21:43 hsperfdata_root

-rwx------. 1 root root  663 5月  20 21:48 ks-script-1AQjlc

drwx------. 3 root root   16 5月  22 08:44 systemd-private-HQgvzl

drwx------. 2 root root   23 5月  22 11:40 ssh-Hon4d3o0kn

-rw-r--r--. 1 root root 1184 5月  22 12:06 0

-rw-r--r--. 1 root root 1184 5月  22 13:24 passwd

5 -v带入外部变量到awk

[root@limt01 tmp]# x=6

[root@limt01 tmp]# awk -v val=$x '{print val}' /etc/passwd|less

6

6

6

6

6 printf函数

命令格式:
printf format,item1,item2……
使用要点:
1.format格式符必须使用
2.不会自动换行,需要手动添加行分隔符
3.format格式符中需要分别为后面的每个item指定一个格式符
格式符:都以%开头,后跟一个字符
%c:显示字符的ASCII码;
%i,%d:显示十进制整数;
%e,%E:科学计数法显示数值;
%f:显示浮点数;
%g,%G:以科学计数法格式或浮点数格式显示数值;
%s:字符串;
%u:无符号整数;
%%:显示%自身

[root@limt01 tmp]# netstat -an|awk '{printf "%-8s %-8s %-8s %-18s %-22s %-15s\n",$1,$2,$3,$4,$5,$6}'

Active   Internet connections (servers           and                    established)   

Proto    Recv-Q   Send-Q   Local              Address                Foreign        

tcp      0        0        127.0.0.1:25       0.0.0.0:*              LISTEN         

tcp      0        0        0.0.0.0:22         0.0.0.0:*              LISTEN         

tcp      0        52       192.168.1.105:22   192.168.1.103:62831    ESTABLISHED    

tcp6     0        0        ::1:25             :::*                   LISTEN         

tcp6     0        0        :::22              :::*                   LISTEN         

udp      0        0        0.0.0.0:68         0.0.0.0:*                             

udp      0        0        192.168.1.105:123  0.0.0.0:*                             

udp      0        0        127.0.0.1:123      0.0.0.0:*                             

udp      0        0        0.0.0.0:123        0.0.0.0:*                             

udp      0        0        0.0.0.0:5353       0.0.0.0:*                             

udp      0        0        0.0.0.0:6480       0.0.0.0:*                             

udp      0        0        0.0.0.0:37782      0.0.0.0:*                          

awk中常见的模式类型:

1 /regular expression/:仅处理能被正则表达式匹配的

[root@limt01 tmp]# awk -F: '/^\<root\>/{print $1,$3}' /etc/passwd

root 0

2  relational expression:关系表达式,结果有真假之分,其结果为非0或非空字符串时为真,否则为假

[root@limt01 tmp]# awk -F: '$3>=500{print $1,$3}' /etc/passwd

polkitd 999

libstoragemgmt 998

chrony 997

limt 1000

awk中常用的控制语句:

1 if else语句
if (condition) statement [ else statement ]
if (condition) {statements;} [ else {statements;} ]

[root@limt01 tmp]# awk -F: '{if ($3>=500) {print $1," is a common user"}else{print $1,"is a systemuser"}}' /etc/passwd

root is a systemuser

bin is a systemuser

daemon is a systemuser

adm is a systemuser

lp is a systemuser

sync is a systemuser

shutdown is a systemuser

。。。

2 while循环语句

语法格式:
while (condition) statement
while (condition) {statements}

[root@limt01 tmp]# awk -F: '$1~/root/{i=1;while(i<=NF){print $i;i+=2}}' /etc/passwd

root

0

root

/bin/bash

3 for循环语句

for (expr1;expr2;expr3) {statements}
for ( variable assignment(条件赋值);condition(循环执行); iteration process(变量修正)) { statement1, statement2, ...}

[root@limt01 tmp]# awk '{for(i=1;i<=NF;i+=2){if (length($i)>=6)print $i }}' /etc/issue

Kernel

4 switch语句

5 break and continue
break[n]:退出当前循环
continue[n]:提前结束本轮循环,直接进入下轮循环

6 next
提前结束对本行的处理而进入下一行的处理

 

数组:因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。

数组,关联数组:array[index-expression]
要遍历数组中的每一个元素,需要使用如下特殊结构:
for (var in array) {for body}
其var会遍历array的索引;而非元素值

[root@limt01 tmp]#  ss -tan |awk '!/State/{state[$1]++}END{for (i in state) {print i,state[i]}}'

LISTEN 4

ESTAB 1

使用脚本进行文本、数据处理:

#!/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

}

 

你可能感兴趣的:(awk)