awk命令

awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息
awk处理过程: 依次对每一行进行处理,然后输出
awk是管道命令,是相对cut那种粗糙处理更加强大些。比如,这个显示的结果中有分隔符不是统一大小的空格字符,无法用cut分割出来

awk命令形式:
awk ‘BEGIN{cmd1;cmd2}pattern{cmd1;cmd2}END{cmd1;cmd2}’ file1 file2
说明:
(1)BEGIN、END是关键字,在BEGIN后面的{}中的命令,通常在处理文本中每一行之前执行,这些命令一般是定义用户自定义的变量;在END后面的{}中的命令,通常在处理完文本中每一行之后执行,这些命令一般是变量之类的;在pattern{}中,如果没有pattern,则是对每一行执行{}中的命令,如果有,则对匹配到的行执行。这里的’‘中内容可以忽略。
(2)只有’{print}'中的内容时候,awk相当于查看文件命令cat,后面的文件可以是多个。
(3)对于{}中的每一个命令都要用;隔开

awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ filename

[-F|-f|-v]:-F指定分隔符,-f调用脚本,-v定义变量 var=value

内置常见的变量

$0 表示整个当前行
$1 每行第一个字段

NF 显示按照-F指定的分隔符分割每行后的区域每行有多少个

NR 每行的记录号,并且是递增,在最后一行的时候,显示的是总行数
FNR 在awk后面跟多个文件时候使用。NR是所有文件合起来的行号,而FNR是每个文件中的行号。
FILENAME 显示当前操作的文件名

\t 制表符
\n 换行符

FS 在BEGIN中定义每行分隔符
OFS 指定打印输出的时候,print里面逗号位置的替代符号。默认是空格来替代。

RS 指定每行行尾的分隔符。默认情况下是换行符\n,也可以指定其他的。

~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
!= 不等于,精确比较
&&  逻辑与
|| 逻辑或

  •        匹配时表示1个或1个以上
    

/[0-9][0-9]+/ 两个或两个以上数字,其中[0-9]代表着其中的一个数字
/[0-9][0-9]*/ 一个或一个以上数字
ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F’[:#/]’ 定义三个分隔符

指定分隔符(filed seperate)
1、默认情况下是空格或者制表符。在awk中,当记录分隔符指定为空字符串时,awk会将多个连续的空白看做一个单一的记录分隔符。此外,awk还会忽略开头和结尾处的空白。

2、指定其他的分隔符
(1)通过-F来指定:来作为分隔符,但是一次只能指定一个,这里可以不用’'或者"“括起来分隔符
awk -F: ‘{print $1,$7}’ /etc/passwd
awk -F”:" ‘{print $1,$7}’ /etc/passwd

(2)通过在BEGIN块中通过内置变量FS赋值的方式,注意赋的值要用“”括起来
awk ‘BEGIN{FS=“:”}{print $1,$7}’ /etc/passwd

(3)指定多个分隔符,使用正则表达式的[]括起来表示,代表其中的任何一个作为分隔符。
这里的[]被解释成正则表达式。
常见的不需要转义的分隔符有: / + - * % # @ ,?{ } .
需要转义的分隔符有:| [ ] ;通常用双引号或者转义字符\转义成普通字符

下面指定:和/作为分隔符
head -1 /etc/passwd|awk -F[😕] ‘{print $1,$10}’
head -1 /etc/passwd|awk -F[/:] ‘{print $1,$10}’

其他常见的分隔符:
(1)awk -F[:;,|-*#] ‘{}’ filename

(2)对于[]作为分隔符的处理
awk -F"[][]" ‘{print $1}’ e
awk -F[][] ‘{print $1,$3}’ e
这里的$2是[]这个里面的内容

zhc-123[zhang]dddd
zhc-123[zhang]dddd

(3)指定多个单词作为分隔符。这里的|是正则表达式中的一部分。表示from字符串或者where字符串。

(4)-F后面跟的分隔符,如果后面跟+,代表将前面多个合并成一个分隔符。
下面不加的话,$3不存在,如果有+的话,b和c之间的分隔符:会当成一个,因此会是c

(5)对于|作为分隔符的时候。由于是shell中的管道符,作为分隔符的时候,要解释成普通字符,要么用“”括起来,要么用转义符\进行转义,同样在[]中也要转义。

(6)以空格和其他分隔符一起来分割。下面是以:和空格作为分隔符来分割

指定打印字符的分隔符
常见的分隔符有\t制表符分割
1、通过内置变量OFS来指定打印出来的每个逗号隔开的字符之间的默认分隔符空格。可以出现在结尾,也可以出现在BEGIN{}中,也可以出现在处理行的前面

下面将$2,$3之间的逗号默认显示成了空格,如果,指定的空格是OFS指定的=,那么就显示=

下面这个没有逗号隔开,即使有OFS="–"也不分割显示。没有逗号的时候,会相连显示。

2、在打印的时候,通过print命令打印字符串的方式来作为输出分隔符,但是对于记录多的情况不适用

打印当中;是回车,是连续的

print函数的打印
1、用""括起来的代表的是字符串,在“”内部,变量会被解释成普通字符,比如$4或者自定义变量Va
要打印变量,直接在“”之外写变量名称,分割域的变量用$1直接写

2、打印分隔符分割的域用 1... 1... 1...n表示;
打印整行用 0 表示或者不写默认就是打印整行打印的 0表示或者不写默认就是打印整行 打印的 0表示或者不写默认就是打印整行打印的n不存在的话,就显示空

3、打印单引号、双引号等特殊字符
在内部打印单引号

在外部用变量值作为单引号,打印变量值

打印双引号

打印其他字符

打印制表符、换行符。必须放在“”之内

打印空行,如果这个文本有n行,则下面的命令就打印n个空行。因为每一行都匹配到,因此会打印n次内容。

4、打印的时候,在{}中的命令,每个命令之间用;进行分割。显示的时候会添加上\n换行符。

5、打印的时候,格式化输出
默认情况下,每个分割命令之间有换行符\n。
在“”中出现的,就是逗号字符,在外面出现的会转换成空格。
在内置变量或者变量之间最好有空格,没有空格的话,$1$2到无所谓,用户自定义可能无法识别,变量直接没有逗号隔开的话,直接就没有分割。

打印内置变量
1、NF

2、NR、FNR、FILENAME。
统计总行数

3、RS断行的分隔符

print & $0
print 是awk打印指定内容的主要命令

-F指定分隔符

awk -F: ‘{print NF}’ /etc/passwd //显示每行有多少字段
awk -F: ‘{print $NF}’ /etc/passwd //将每行第NF个字段的值打印出来
awk -F: ‘NF4 {print }’ /etc/passwd //显示只有4个字段的行
awk -F: ‘NF>2{print $0}’ /etc/passwd //显示每行字段数量大于2的行
awk ‘{print NR,KaTeX parse error: Expected 'EOF', got '}' at position 2: 0}̲' /etc/passwd …NF,“\t”,$0}’ /etc/passwd //依次打印行号,字段数,最后字段值,制表符,每行内容
awk -F: 'NR
5{print}’ /etc/passwd //显示第5行
awk -F: ‘NR5 || NR6{print}’ /etc/passwd //显示第5行和第6行
route -n|awk ‘NR!=1{print}’ //不显示第一行

自定义输出格式

显示/etc/passwd中按照:分隔,每一行共有多少个字段。这里是7个字段

将每一行中第几个字段打印出来,因为这个变量NF的值已经是7了,所以打印的第7个字段的值

显示只有4个字段的行的值,显示小于4个字段的值

显示每行的行号

依次显示每行的行号,总共有多个字段,最好一个字段的值,分隔符,全行信息

显示指定行的信息,如下显示/etc/passwd中的第一行和第三行

不显示指定行的信息。显示前4行结果,但是不显示其中的第二行

//匹配代码块
可以所有字段来匹配,也可以指定字段来匹配

//纯字符匹配 !//纯字符不匹配 字符值多个匹配 /a1|a2/ 【匹配一行所有字符中含有a1或者a2的字符的那行】
~//字段值匹配 !~//字段值不匹配 ~/a1|a2/字段值匹配a1或a2 【匹配指定字段中含有a1或者a2字符的那行】
匹配数字/[2][7][7]/ 不匹配!/[2][7][7]/ 【*代表着0或者多个,前两位是27,第三位的7可以有,也可以没有的行】
awk ‘/mysql/’ /etc/passwd

awk ‘/mysql/{print }’ /etc/passwd
awk ‘/mysql/{print $0}’ /etc/passwd //三条指令结果一样
awk ‘!/mysql/{print $0}’ /etc/passwd //输出不匹配mysql的行
awk ‘/mysql|mail/{print}’ /etc/passwd
awk ‘!/mysql|mail/{print}’ /etc/passwd
awk -F: ‘/mail/,/mysql/{print}’ /etc/passwd //区间匹配

awk ‘/[2][7][7]*/{print $0}’ /etc/passwd //匹配包含27为数字开头的行,如27,277,2777…

awk -F: ‘$1~/mail/{print $1}’ /etc/passwd //$1匹配指定内容才显示
awk -F: ‘{if($1~/mail/) print $1}’ /etc/passwd //与上面相同
awk -F: ‘$1!~/mail/{print $1}’ /etc/passwd //不匹配
awk -F: ‘$1!~/mail|mysql/{print $1}’ /etc/passwd
匹配/etc/passwd中含有root字符的这一行,并显示行号

匹配/etc/passwd中既含有root字符,又含有mysql字符的这一行,并显示行号

匹配/etc/passwd中既不含有root字符,又不含有mysql字符的这一行,并显示行号

匹配squid和mysql之间的值,区间匹配

匹配数字,下面这个匹配以27开头的数字,*代表前面的这个7可以是0个或者多个,也就是匹配27,277,2777等等的

字段匹配,$1字段匹配root字符,显示行号和正行内容

awk -F: ‘{if($1~/mail/) print $1}’ /etc/passwd
awk -F: ‘$1!~/mail/{print $1}’ /etc/passwd
awk -F: ‘$1!~/mail|mysql/{print $1}’ /etc/passwd

IF语句
必须用在{}中,且比较内容用()扩起来
awk -F: ‘{if($1~/mail/) print $1}’ /etc/passwd //简写
awk -F: ‘{if($1~/mail/) {print $1}}’ /etc/passwd //全写
awk -F: ‘{if($1~/mail/) {print $1} else {print $2}}’ /etc/passwd //if…else…

条件表达式
== != > >=
awk -F":" ‘$1==“mysql”{print $3}’ /etc/passwd
awk -F":" ‘{if($1==“mysql”) print $3}’ /etc/passwd //与上面相同
awk -F":" ‘$1!=“mysql”{print $3}’ /etc/passwd //不等于
awk -F":" ‘$3>1000{print $3}’ /etc/passwd //大于
awk -F":" ‘$3>=100{print $3}’ /etc/passwd //大于等于
awk -F":" ‘$3<1{print $3}’ /etc/passwd //小于
awk -F":" ‘$3<=1{print $3}’ /etc/passwd //小于等于

逻辑运算符
&& ||
awk -F: ‘$1~/mail/ && $3>8 {print }’ /etc/passwd //逻辑与,$1匹配mail,并且$3>8
awk -F: ‘{if($1~/mail/ && $3>8) print }’ /etc/passwd
awk -F: ‘$1~/mail/ || $3>1000 {print }’ /etc/passwd //逻辑或
awk -F: ‘{if($1~/mail/ || $3>1000) print }’ /etc/passwd

数值运算
awk -F: ‘$3 > 100’ /etc/passwd
awk -F: ‘$3 > 100 || $3 < 5’ /etc/passwd
awk -F: ‘$3+$4 > 200’ /etc/passwd
awk -F: ‘/mysql|mail/{print $3+10}’ /etc/passwd //第三个字段加10打印
awk -F: ‘/mysql/{print $3-$4}’ /etc/passwd //减法
awk -F: ‘/mysql/{print $3*$4}’ /etc/passwd //求乘积
awk ‘/MemFree/{print $2/1024}’ /proc/meminfo //除法
awk ‘/MemFree/{print int($2/1024)}’ /proc/meminfo //取整

输出分隔符OFS
awk ‘$6 ~ /FIN/ || NR1 {print NR,$4,$5,$6}’ OFS=“\t” netstat.txt
awk '$6 ~ /WAIT/ || NR
1 {print NR,$4,$5,$6}’ OFS=“\t” netstat.txt
//输出字段6匹配WAIT的行,其中输出每行行号,字段4,5,6,并使用制表符分割字段

输出处理结果到文件
①在命令代码块中直接输出 route -n|awk ‘NR!=1{print > “./fs”}’
②使用重定向进行输出 route -n|awk ‘NR!=1{print}’ > ./fs

格式化输出
netstat -anp|awk ‘{printf “%-8s %-8s %-10s\n”,$1,$2,$3}’
printf表示格式输出
%格式化输出分隔符
-8长度为8个字符
s表示字符串类型
打印每行前三个字段,指定第一个字段输出字符串类型(长度为8),第二个字段输出字符串类型(长度为8),
第三个字段输出字符串类型(长度为10)
netstat -anp|awk ‘$6==“LISTEN” || NR1 {printf “%-10s %-10s %-10s \n”,$1,$2,$3}’
netstat -anp|awk '$6
"LISTEN" || NR==1 {printf “%-3s %-10s %-10s %-10s \n”,NR,$1,$2,$3}’

输出了行头,和LISTEN的字段

IF语句
awk -F: ‘{if($3>100) print “large”; else print “small”}’ /etc/passwd
small
small
small
large
small
small
awk -F: ‘BEGIN{A=0;B=0} {if($3>100) {A++; print “large”} else {B++; print “small”}} END{print A,“\t”,B}’ /etc/passwd
//ID大于100,A加1,否则B加1
awk -F: ‘{if($3<100) next; else print}’ /etc/passwd //小于100跳过,否则显示
awk -F: ‘BEGIN{i=1} {if(i<NF) print NR,NF,i++ }’ /etc/passwd
awk -F: ‘BEGIN{i=1} {if(i<NF) {print NR,NF} i++ }’ /etc/passwd
另一种形式
awk -F: ‘{print ($3>100 ? “yes”:“no”)}’ /etc/passwd
awk -F: ‘{print ($3>100 ? $3":\tyes":$3":\tno")}’ /etc/passwd

开头定义两个变量A,B初始值为0,如果$3大于100,动作就是A+1,并打印为large,否则如果小于100,B+1,打印small,结尾输出A,B的结果。从图中可以看出,大于100的有11个,小于100的有31个

下图中显示:如果大于100,就打印yes,如果小于100,就显示no

while语句
awk -F: ‘BEGIN{i=1} {while(i<NF) print NF,$i,i++}’ /etc/passwd
7 root 1
7 x 2
7 0 3
7 0 4
7 root 5
7 /root 6

数组
netstat -anp|awk ‘NR!=1{a[$6]++} END{for (i in a) print i,“\t”,a[i]}’
netstat -anp|awk ‘NR!=1{a[$6]++} END{for (i in a) printf “%-20s %-10s %-5s \n”, i,“\t”,a[i]}’
9523 1
9929 1
LISTEN 6
7903 1
3038/cupsd 1
7913 1
10837 1
9833 1

应用1
awk -F: ‘{print NF}’ helloworld.sh //输出文件每行有多少字段
awk -F: ‘{print $1,$2,$3,$4,$5}’ helloworld.sh //输出前5个字段
awk -F: ‘{print $1,$2,$3,$4,$5}’ OFS=‘\t’ helloworld.sh //输出前5个字段并使用制表符分隔输出
awk -F: ‘{print NR,$1,$2,$3,$4,$5}’ OFS=‘\t’ helloworld.sh //制表符分隔输出前5个字段,并打印行号

应用2
awk -F’[:#]’ ‘{print NF}’ helloworld.sh //指定多个分隔符: #,输出每行多少字段
awk -F’[:#]’ ‘{print $1,$2,$3,$4,$5,$6,$7}’ OFS=‘\t’ helloworld.sh //制表符分隔输出多字段
应用3
awk -F’[:#/]’ ‘{print NF}’ helloworld.sh //指定三个分隔符,并输出每行字段数
awk -F’[:#/]’ ‘{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12}’ helloworld.sh //制表符分隔输出多字段

应用4
计算/home目录下,普通文件的大小,使用KB作为单位
ls -l|awk ‘BEGIN{sum=0} !/^d/{sum+=$5} END{print “total size is:”,sum/1024,“KB”}’
ls -l|awk ‘BEGIN{sum=0} !/^d/{sum+=$5} END{print “total size is:”,int(sum/1024),“KB”}’ //int是取整的意思
END 是在所有文件行寻完后,计算出来的SUM值,sum是一个全局变量,每次都是加上$5

应用5
统计netstat -anp 状态为LISTEN和CONNECT的连接数量分别是多少
netstat -anp|awk ‘$6~/LISTEN|CONNECTED/{sum[$6]++} END{for (i in sum) printf “%-10s %-6s %-3s \n”, i," ",sum[i]}’

应用6
统计/home目录下不同用户的普通文件的总数是多少?
ls -l|awk ‘NR!=1 && !/^d/{sum[$3]++} END{for (i in sum) printf “%-6s %-5s %-3s \n”,i," ",sum[i]}’

mysql 199
root 374
统计/home目录下不同用户的普通文件的大小总size是多少?
ls -l|awk ‘NR!=1 && !/^d/{sum[$3]+=$5} END{for (i in sum) printf “%-6s %-5s %-3s %-2s \n”,i," ",sum[i]/1024/1024,“MB”}’

应用7
输出成绩表

awk ‘BEGIN{math=0;eng=0;com=0;printf “Lineno. Name No. Math English Computer Total\n”;printf “------------------------------------------------------------\n”}{math+=$3; eng+=$4; com+=$5;printf “%-8s %-7s %-7s %-7s %-9s %-10s %-7s \n”,NR,$1,$2,$3,$4,$5,$3+$4+$5} END{printf “------------------------------------------------------------\n”;printf “%-24s %-7s %-9s %-20s \n”,“Total:”,math,eng,com;printf “%-24s %-7s %-9s %-20s \n”,“Avg:”,math/NR,eng/NR,com/NR}’ test0

[root@localhost home]# cat test0
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62

awk -F"|" ‘{print(“INSERT INTO OS_BASE_INFO_T (IPADDR,CPU_TYPE,MEMOR_SIZE,OS_TYPE,OS_RELEASE,SSH_VERSION,GATHER_TIME) VALUES (”"’‘’“$1”‘’‘“”,“”’‘’“$2”‘’‘“”,“”’‘’“$3”‘’‘“”,“”’‘’“$4”‘’‘“”,“”’‘’“$5”‘’‘“”,“”’‘’“”‘’‘“”)“”;")}’ c
INSERT INTO game_broker values (‘addr:172.16.0.132’,‘Intel® Celeron® CPU 1005M @ 1.90GHz’,‘1914844kB’,‘release’,‘CentOS release 6.3 (Final)’,‘’);
[root@dg2 ~]#

[root@dg2 ~]# awk -F"|" ‘{print “”$1""}’ c
addr:172.16.0.132
[root@dg2 ~]#
awk -F"|" -v datevar=“date +%Y%m%d” ‘{print(“INSERT INTO OS_BASE_INFO_T (IPADDR,CPU_TYPE,MEMOR_SIZE,OS_TYPE,OS_RELEASE,SSH_VERSION,GATHER_TIME) VALUES (”"’‘’“$1”‘’‘“”,“”’‘’“$2”‘’‘“”,“”’‘’“$3”‘’‘“”,“”’‘’“$4”‘’‘“”,“”’‘’“$5”‘’‘“”,“”’‘’“$6”‘’‘“”,“”’‘’“datevar”‘’‘“”)“”;")}’ c

[root@dg2 ~]# awk -F"|" -v datevar=“date +%Y%m%d” ‘{print(“INSERT INTO OS_BASE_INFO_T (IPADDR,CPU_TYPE,MEMOR_SIZE,OS_TYPE,OS_RELEASE,SSH_VERSION,GATHER_TIME) VALUES (”"’‘’“$1”‘’‘“”,“”’‘’“$2”‘’‘“”,“”’‘’“$3”‘’‘“”,“”’‘’“$4”‘’‘“”,“”’‘’“$5”‘’‘“”,“”’‘’“$6”‘’‘“”,“”’‘’“datevar”‘’‘“”)“”;")}’ c
INSERT INTO OS_BASE_INFO_T (IPADDR,CPU_TYPE,MEMOR_SIZE,OS_TYPE,OS_RELEASE,SSH_VERSION,GATHER_TIME) VALUES (‘addr:172.16.0.132’,‘Intel® Celeron® CPU 1005M @ 1.90GHz’,‘1914844kB’,‘release’,‘CentOS release 6.3 (Final)’,‘’,‘20200919’);
INSERT INTO OS_BASE_INFO_T (IPADDR,CPU_TYPE,MEMOR_SIZE,OS_TYPE,OS_RELEASE,SSH_VERSION,GATHER_TIME) VALUES (‘addr:172.16.0.133’,‘Intel® Celeron® CPU 1005M @ 1.90GHz’,‘1914844kB’,‘release’,‘CentOS release 6.3 (Final)’,‘’,‘20200919’);
INSERT INTO OS_BASE_INFO_T (IPADDR,CPU_TYPE,MEMOR_SIZE,OS_TYPE,OS_RELEASE,SSH_VERSION,GATHER_TIME) VALUES (‘addr:172.16.0.134’,‘Intel® Celeron® CPU 1005M @ 1.90GHz’,‘1914844kB’,‘release’,‘CentOS release 6.3 (Final)’,‘’,‘20200919’);
INSERT INTO OS_BASE_INFO_T (IPADDR,CPU_TYPE,MEMOR_SIZE,OS_TYPE,OS_RELEASE,SSH_VERSION,GATHER_TIME) VALUES (‘addr:172.16.0.135’,‘Intel® Celeron® CPU 1005M @ 1.90GHz’,‘1914844kB’,‘release’,‘CentOS release 6.3 (Final)’,‘’,‘20200919’);
[root@dg2 ~]#

awk -v datevar=“date +%Y%m%d” -v IP=“172.16” ‘{print("INSERT INTO OS_FILESYSTEM_INFO_T( “”’‘’“IPADDR”‘’‘“”,FILESYSTEM ,CAPACITY,USE_RATE,MEMO,GATHER_DATE ) VALUES (“”’‘’“IP”‘’‘“”,“”’‘’“$1”‘’‘“”,“”’‘’“$2”‘’‘“”,“”’‘’“$3”‘’‘“”,“”’‘’“$4”‘’‘“”,“”’‘’“$5”‘’‘“”,“”’‘’“datevar”‘’‘“”)“”;")}’ d

df -h|sed ‘1d;/ /!N;s/\n//;s/ +/ /;’

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值