awk命令的使用

awk命令

格式

awk [ -F 字段分隔符] ‘commands’ filename
默认以空格或tab键为分隔符

以冒号作为分隔符,则必须指明-F选项,如:awk -F: ‘commands’ filename

-F fs 指定以 fs 作为输入行的分隔符,awk 命令默认分隔符为空格或制表符

-v var=val 在执行处理过程之前,设置一个变量 var,并给其设备初始值为 val

awk命令的完整格式:awd [-F field-separator] ‘匹配规则{执行命令}’ filename

整个commands是用单引号(’’)括起,而其中的执行命令部分需要用大括号({})括起来

在 awk 程序执行时,如果没有指定执行命令,则默认会把匹配的行输出;如果不指定匹配规则,则默认匹配文本中所有的行

匹配规则

awk保留字 BEGIN 在awk程序一开始,尚未读取任何数据之前执行。BEGIN 后的动作只在程序开始时执行一次

awk保留字 END 在awk程序处理完所有数据,即将结束时执行。END 后的动作只在程序结束时执行一次

关系运算符 > 大于
< 小于
>= 大于等于
<= 小于等于
== 等于。用于判断两个值是否相等。如果是给变量赋值,则使用"=”
!= 不等于
匹配表达式 ~(匹配) value ~ /regexp/ 如果value匹配/regexp/,则返回真
!~(不匹配) value !~ /regexp/ 如果value不匹配/regexp/,则返回真
正则表达式 /正则表达式/ 如果在“//”中可以写入字符,则也可以支持正则表达式,如:/root/表示匹配含有root的行。
逻辑运算符 && 逻辑与
|| 逻辑或

[root@haha ~]# awk -F: '$7~ /bash$/ {print $1}' /etc/passwd
root
haha
##以:为分隔符查看/etc/passwd文件,如果第七列匹配以/bash结尾的字符串,就输出对应行的第一列

数据字段变量

$0 代表整个文本行
$1 代表文本行中的第 1 个数据字段
$2 代表文本行中的第 2 个数据字段
$n 代表文本行中的第 n 个数据字段

显示passwd文件中第1个第6个字段的信息
awk -F: ‘{print $1"\t"$6}’ /etc/passwd

执行命令

awk的执行命令在大括号{ }内指明。动作大多数用来打印(即print指令)
动作(Action):
格式化输出(print);
流程控制语句(if、while、for等);

(5)awk中的BEGIN和END
awk [options] ‘BEGIN{ print “start” } 匹配规则{ commands } END{ print “end” }’ filename

BEGIN:
BEGIN 的执行时机是"在 awk 程序一开始,尚未读取任何数据之前"。一旦BEGIN后的动作执行一次,当awk开始从文件中读入数据时,BEGIN 的条件就不再成立,所以BEGIN定义的动作只能被执行一次。通过BEGIN开始块我们可以用来设置变量,设置标题

[root@haha ~]# awk -F: 'BEGIN {print "username and loginshell"} $3>=500 {print $1 "\t" $7}' /etc/passwd
#这里定义了两个动作
   #第一个动作使用BEGIN条件,所以会在读入文件数据前打印"print username and loginshell" (只会执行一次)
   #第二个动作会在条件满足时打印文件的第1个字段和第7个字段

END:
END也是awk的保留字,不过刚好和 BEGIN 相反。END 是在 awk 程序处理完所有数据,即将结束时执行的。END 后的动作只在程序结束时执行一次。

[root@haha ~]# awk -F: 'BEGIN {print "print username and loginshell"} $3>=500 {print $ "\t" $7} END {print "The end"}' /etc/passwd
##输出结尾输入"The End",这并不是文档本身的内容,而且只会执行一次

awk变量

awk自定义变量

awk -v varname=value 变量名区分字符大小写

[root@haha ~]# awk -v var=”统计用户数” -v count=0 -F: ‘BEGIN{
    
    print var} {
    
    count++} END{
    
    print “user count is:,count}/etc/passwd

在program中直接定义,定义的时候用分号,打印变量跟之前一样,用逗号隔开,不需要用美元符号(BENGIN中定义)

[root@haha ~]# awk 'BEGIN{name="haha";age="26";sex="man";print name,age,sex}'
haha 26 man

命令行定义

[root@haha ~]# var=“ha ha”
[root@haha ~]# awk -v var1=“$var” ‘BEGIN{
    
    print var1}’
##不在awk中定义,是打印不出来的
haha

awk内置变量(预定义变量)

$n 当前记录(当前行)的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段
$0 这个变量包含执行过程中当前行的文本内容
FILENAME 当前输入文件的名
FS 字段分隔符(默认是任何空格)
NF 表示字段数,在执行过程中对应于当前的字段数
NR 表示记录数,在执行过程中对应于当前的行号
FNR 各文件分别计数的行号

[root@haha ~]# cat test.txt
haha 25 man
hehe 25 man
heihei 25 man
[root@haha ~]# cat test1.txt
xixi 25 man
hengheng 25 man

NF:打印出每行有多少列:

[root@haha ~]# awk ‘{
    
    print NF}’ test.txt
3
3
3

NF:引用第一列和最后一列

[root@haha ~]# awk ‘{
    
    print $(NF-2),$NF}’test.txt
haha man
hehe man
heihei man

NR:每行行号

[root@haha ~]# awk ‘{
    
    print NR“),$0}’ test.txt
1)haha 25 man
2)hehe 25 man
3)heihei 25 man

FNR:awk支持多文件scan,使用NR接续排号,使用FNR单独排号

[root@haha ~]# awk ‘print NR“),$0’ test.txt test1.txt
1)haha 25 man
2)hehe 25 man
3)heihei 25 man
4)xixi 25 man
5)hengheng 25 man
[root@haha ~]# awk ‘print FNR“),$0’test.txt test1.txt
1)haha 25 man
2)hehe 25 man
3)heihei 25 man
1)xixi 25 man
2)hengheng 25 man

FS:分隔符
常见的写法: -F: -F, -F[ /,]

[root@haha ~]# echo “a b c d” | awk ‘{
    
    print $2}’
b
[root@haha ~]# echo “a,b,c,d” | awk -F,{
    
    print $2}’
b
[root@haha ~]# echo “a,b,c,d” | awk -F“,” ‘{
    
    print $2}’
b
[root@haha ~]# echo “a b,c%d” | awk -F“[ ,%]” ‘{
    
    print $2}’
b
[root@haha ~]# echo “a   b,,c%%%d” | awk -F“[ ,%]+” ‘{
    
    print $2}’
b

例 :

[root@haha ~]# ls -l | awk 'BEGIN{size=0}{size+=$5}END{print "Total is:"size/1024/1024"MB"}'
统计某个目录下的文件占用字节数,以MB显示

[root@haha ~]# ls -l /etc/ | awk 'BEGIN{sum=0}/^[^d]/{print $9  "\t"  $5;sum+=$5}END{print "Total size:"sum/1024/1024"MB"}'
统计某个目录下每个文件的大小及其总和,但要排除子目录

[root@haha ~]# ifconfig ens33 | grep “inet\>| awk ‘{
    
    print $2}192.168.13.14
提取IP地址

[root@haha ~]# echo “haha heihei hehe xixi” | awk ‘{
    
    print $3}’
hehe
[root@haha ~]# echo “haha heihei hehe xixi” | awk ‘{
    
    print $(NF-1)}’
hehe
关系运算

[root@haha ~]# awk  -F: ‘$3<1000{
    
    print $1<======>”$NF}/etc/passwd
打印passwd文件中用户UID小于10的用户名和它登录使用的登录shell

awk -F: ‘$3>=1000 && $NF==/bin/bash”{
    
    print $1,$NF}/etc/passwd
打印系统中能够正常登录的普通用户

[root@haha ~]# free -m | grep -i "mem" | awk '{printf "%.2f\n",$3/$2*100}'
统计当前内存的使用率
##printf命令按照指定的格式显示输出。
##printf命令格式:printf 	“打印格式”  显示内容
%2.f就是打印格式,表保留小数后两位,f代表浮点数

awk控制语句

if语句

if (条件) print
if(条件){print}else{print}
if(条件){print}else if(条件){print}else{print}
##else if == elif
if语句使用环境:对awk来说,要对取得的整行或某个字段做条件判断

[root@haha ~]# awk -F: '{if($3<1000) {print "system_user="$1} else {print "ordinary_user="$1}}' /etc/passwd
##如果uid小于1000,就打印系统用户:$1,否则打印普通用户:$1

[root@haha ~]# awk -F: '{if($3==0){print "Administrator:"$1}else if($3<1000){print "system_user:"$1}else{print "ordinary_user:"$1}}' /etc/passwd
##如果uid=0就打印系统管理员root,如果uid<1000就打印程序用户,否则打印普通用户

[root@haha ~]# df -hT | awk -F"[ %]+" '/^\/dev/{if($6>25){print $1"\t"$6"%"}}'
##统计分区使用率,输出超过25%的分区信息

while循环

语句:while(条件){语句} 如果条件为“真”进入循环,条件为“假”退出循环
在进行运算结果统计时,可以使用符号+=,意思是说我们可以把增加的结果赋值给符号的左边的变量,对哪个域操作就把哪个域写在符号的右边,如Total+=$3
while语句使用使用环境:在awk中对一行内容中的多个字段一个个处理

[root@haha ~]# awk '{total=total+$5}END{print total}' test.txt
[root@haha ~]# awk '{total+=$5}END{print total}' test.txt
总数=总数+第五列数据(列数据的和)
END打印总数

[root@haha ~]# awk '{total=0;i=1;while(i<=NF){total+=$i;i++}; print total}' test.txt
##总数为0,赋值1给变量i,当i小于等于字段域时,总数加上i对应域的数据,i递增,循环结束打印总数(行数据的和)

[root@haha ~]# awk 'NR>1{total=0;i=5;while(i<=$(NF-2)){total+=$i;i++};print $1,total}' test.txt
##匹配规则NR>1,执行命令:赋值total,赋值i,当i小于等于(NF-2)时,总数=总数加上i对应列的数据,然后打印出来总数

for循环

语法:for(变量赋值;条件;迭代){命令}
语法:for (var in array){语句}

[root@haha ~]# awk '{total=0;for(i=1;i<=NF;i++){total+=$i}; print total}' test.txt
##总数为0,i=1,当i小于等于字段个数时,总数=总数和i对应字段的数据相加,i递增,结束for循环后,打印总数

偶数(next)

打印奇数或偶数行

awk ‘NR%2==0{print NR,$0}’ /root/test.txt
行数模2,余数为0,为偶数行
行数模2,余数为1,为奇数行

数组

数组是一个包含一系列元素的集合
格式:
zex[1]=”haha”
zex[2]=”heihei”

zex :为数组名称
[1]、[2]:为数组元素下标,可以理解为数组的第1个元素、数组的第2个元素
“haha”、“heihei”: 元素内容

数组变量赋值格式

var[index]=element
说明:var====>是数组名
index===>是关联数组的下标
element===>是数组的元素值

数字做数组下标:
array[1]=”haha”
array[2]=”heihei”

字符串做数组下标:
array[“first”]=”www”
array[“last”]=”name”
在引用数组变量的时候,必须要包含它的下标值,然后通过下标值来提取它相对应的元素值

awk书写格式

[root@haha ~]# awk 'BEGIN{ \
> test["a"]="haha" \
> test["b"]="heihei" \
> test["c"]="hehe" \
> print test["b"] \
> }'
显示结果:
heihei
也可以写成:
#awk 'BEGIN{test["a"]="haha";test["b"]="heihei";test["c"]="hehe";print test["b"]}'

遍历数组中的元素

for(var in array){print array[var]}

[root@haha ~]# awk ‘BEGIN{
    
     \
>test[“a”]=“haha” \
>test[“b”]=“hehe” \
>for(i in test) \
>{
    
    print “index:”i,-----------value:”test[i] \
>}’
index:a ----------value:haha
index:b ----------value:hehe

删除数组元素

花括号命令中添加 delete array[下标]

[root@haha ~]# awk 'BEGIN{test["a"]="haha";test["b"]="hehe";test["c"]="heihei";for(i in test){print i,test[i]};print "+++++++++++++++";delete test["b"];for(i in test){print i,test[i]}}'

数组应用

array[“index”]++ 每循环一次这个索引所对应的元素值加1(初始值默认是0[root@haha ~]# netstat -antpu | awk'/^tcp\>/{
    
    test[$6]++}END{
    
    for(i in tes
t){
    
    print i,test[i]}}'
##查看tcp连接LIsten和Estableshed出现的次数

[root@haha ~]# awk -F“[/]+” ‘{
    
    print $2}’ test.txt | sort | uniq -c
##查看相同字符串出现的次数

[root@haha ~]# awk ‘{
    
    test[$1]++}END{
    
    for(i in test){
    
    print i,test[i]}}’ test.txt
##查看相同字符串出现的次数

猜你喜欢

转载自blog.csdn.net/weixin_52441468/article/details/112642630