Hits

linux awk 介绍

每天一个linux命令-awk

awk

netstat -an | head -n 30 > netstat.txt  // 保存30条网络端口占用情况

awk '{print $1, $4}' netstat.txt // 打印第1列和第4列,$0查看所有列

awk '{printf "%-8s %-8s %-8s %-26s %-26s %-15s\n",$1,$2,$3,$4,$5,$6}' netstat.txt // printf 格式化打印

awk '$3==0 && $6=="LISTEN" ' netstat.txt // 查看指定条件的内容,其他比较运算法 !=, >, <, >=, <=

awk '$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}' netstat.txt // NR显示表头第几行,可以用>=等符号

内建变量

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

awk '$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}' netstat.txt

awk  'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd // 以:分割,打印对应字段

awk  -F: '{print $1,$3,$6}' /etc/passwd // 跟上面一样

awk -F '[;:]' /etc/passwd // 指定多个分隔符 ; 和 :

awk  -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd // 输出用\t 也就是tab分隔

awk '$6 ~ /EST/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt  // 匹配含有EST字符的对应的列,~模式开始,// 中就是匹配的模式

awk '/LISTEN/' netstat.txt // 跟grep功能一样,过滤含有LISTEN的行

awk '/LISTEN|TIME/' netstat.txt // 匹配含有LISTEN或者TIME

awk '$6 !~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt // 匹配第6列不含有WAIT的指定列

awk '!/WAIT/' netstat.txt // 跟上面的功能一样

拆分文件

awk 'NR!=1{print > $6}' netstat.txt // NR!=1表示不处理表头,按照第6列分割文件

awk 'NR!=1{print $4,$5 > $6}' netstat.txt // 将第4,5列输出到按照第6列切分的文件中

// 按第6列切分不同值的行到指定文件
$ awk 'NR!=1{if($6 ~ /EST|TIME/) print > "1.txt";
else if($6 ~ /LISTEN/) print > "2.txt";
else print > "3.txt"}' netstat.txt

统计

ls -l  *.sh *.go | awk '{sum+=$5} END {print sum}' // 计算当前目录下所有go文件和sh文件的文件大小总和

awk 'NR!=1{a[$6]++;} END {for(i in a) print i ", " a[i];}' netstat.txt // 统计第6列出现的次数分别是多少

// 统计每个用户的进程占用了多少内存(sum的是RSS那一列)
ps aux | awk 'NR!=1{a[$1]+=$6;} END { for(i in a) print i ", " a[i]"KB";}' 

awk脚本

在上面我们看到一个关键字,END 关键字,END 的意思是“处理完所有的行的标识”,既然说到了 END 就有必要介绍一下 BEGIN,这两个关键字意味着执行前和执行后的意思:

  • BEGIN {这里面放的是执行前的语句}
  • END {这里面放的是处理完所有的行后要执行的语句}
  • {这里面放的是处理每一行时要执行的语句}

有如下一个文件 score.txt

cat score.txt

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脚本如下:

cat cal.awk

#!/usr/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\n", $1,$2,$3,$4,$5,$3+$4+$5
}

#运行后
{   
    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
}

// 执行./cal.awk score.txt 就可以看到结果了。

环境变量

使用 -v 参数和 ENVIRON 。使用 ENVIRON 的环境变量需要export

x=5
y=10
export y
echo $x $y
// 输出5,10

// 第四行+val  val为0,所以不变,$5+y y的值为环境变量10所以都加10
awk -v val=$x '{print $1,$2,$3,$4+val,$5+ENVIRON["y"]}' OFS="\t" score.txt 

几个花活

最后看一下下面几个例子

// 从file文件中找出长度大于80的行
awk 'length>80' file
 
// 按连接数查看客户端IP
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr
 
// 打印99乘法表
seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}'

本文链接:参与评论 »

--EOF--

提醒:本文最后更新于 135 天前,文中所描述的信息可能已发生改变,请谨慎使用。

专题「Linux相关知识」的其它文章 »

Comments