Linux命令学习之-awk

190 阅读7分钟

awk命令说明

wk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等

命令格式和参数

awk [options] 'script' var=value file(s)

awk [options] -f scriptfile var=value file(s)

常用命令选项

  • -F fs fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:,默认的分隔符是连续的空格或制表符
  • -v var=value 赋值一个用户定义变量,将外部变量传递给awk
  • -f scripfile 从脚本文件中读取awk命令
  • -m[fr] val 对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。
  • $NF 代表最后一个字段
  • &&
  • ||
  • FS 输入分隔符,与-F分隔符一样
  • OFS 输出字段分隔符
  • RS 输入记录分隔符
  • $0 显示整行
  • NR 内置字段,表示第几行
  • 1...N 第一个字段到第N个字段,
$1表示第一个字段,$(NF-1)表示倒数第二个字段的值

awk脚本基本结构

awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file

awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被 单引号 中,例如:

 awk 'BEGIN{ i=0 } { i++ } END{ print i }'  filename

总的来说,awk脚本是由模式和操作组成的

模式可以是以下任意一个:

  • /正则表达式/:使用通配符的扩展集。
  • 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
  • 模式匹配表达式:用运算符~(匹配)和!~(不匹配)。
  • BEGIN语句块、pattern语句块、END语句块:参见awk的工作原理

操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是:

  • 变量或数组赋值
  • 输出命令
  • 内置函数
  • 控制流语句

awk的工作原理

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
  • 第一步:执行BEGIN{ commands }语句块中的语句;
  • 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
  • 第三步:当读至输入流末尾时,执行END{ commands }语句块。

BEGIN语句块 在awk开始从输入流中读取行 之前 被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

END语句块 在awk从输入流中读取完所有的行 之后 即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

pattern语句块 中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

内置函数

print : 打印

printf : 格式化打印

%s : 字符串

%d: 数字

- : 左对齐

+ : 右对齐

15 : 至少占用15字符

命令表达式和流程控制语法

比较表达式

  • > : 大于
  • < : 小于
  • >= : 大于等于
  • <= : 小于等于
  • ~ : 正则匹配(包含)
  • !~ : 正则匹配(不包含)
  1. 打印第三列 < 第四列的行
guanwu@master:~/learnshell/awk$ awk -F: '$4 > $3{print $0}' /etc/passwd | head -5
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 
  1. 打印结尾匹配或者不匹配的行,匹配使用 ~, 不匹配使用 !~
guanwu@master:~/learnshell/awk$ awk -F: '$NF ~ /bash/{print $0}' /etc/passwd | head  -5
root:x:0:0:root:/root:/bin/bash
guanwu:x:1000:1000:guanwu,,,:/home/guanwu:/bin/bash
guanwu@master:~/learnshell/awk$ awk -F: '$NF !~ /bash/{print $0}' /etc/passwd | head  -5
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 
  1. 打印第三行
guanwu@master:~/learnshell/awk$ awk -F: 'NR == 3{print $0}' /etc/passwd
bin:x:2:2:bin:/bin:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

算术表达式

  • +
  • -
  • *
  • /
  • %

加法

guanwu@master:~/learnshell/awk$ awk -F: '$3 + $4 > 2000{print $0}' /etc/passwd
sync:x:4:65534:sync:/bin:/bin/sync
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
kernoops:x:113:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
gnome-initial-setup:x:126:65534::/run/gnome-initial-setup/:/bin/false
sshd:x:130:65534::/run/sshd:/usr/sbin/nologin
_rpc:x:131:65534::/run/rpcbind:/usr/sbin/nologin
statd:x:132:65534::/var/lib/nfs:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

乘法

guanwu@master:~/learnshell/awk$ awk -F: '$3 * $4 > 2000{print $0}' /etc/passwd | head -5
sync:x:4:65534:sync:/bin:/bin/sync
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:102:105::/nonexistent:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

取余

打印双数行, NR表示当前第几行, 使用printf格式化打印,类似c语言, %2d表示向右对齐,占两位

guanwu@master:~/learnshell/awk$ awk  -F: 'NR % 2 == 0{printf("%2d %s %s\n",NR, " ",  $0);}' /etc/passwd | head -5
 2   daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
 4   sys:x:3:3:sys:/dev:/usr/sbin/nologin
 6   games:x:5:60:games:/usr/games:/usr/sbin/nologin
 8   lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
10   news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

逻辑表达式

  • && 逻辑与
  • || 逻辑或
  • ! 逻辑非 逻辑与
guanwu@master:~/learnshell/awk$ awk -F: '$3 + $4 > 2000 && $3 * $4 > 2000{print $0}' /etc/passwd
sync:x:4:65534:sync:/bin:/bin/sync
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
kernoops:x:113:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
gnome-initial-setup:x:126:65534::/run/gnome-initial-setup/:/bin/false
sshd:x:130:65534::/run/sshd:/usr/sbin/nologin
_rpc:x:131:65534::/run/rpcbind:/usr/sbin/nologin
statd:x:132:65534::/var/lib/nfs:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

逻辑或

guanwu@master:~/learnshell/awk$ awk -F: '$3 + $4 > 2000 || $3 * $4 > 2000{print $0}' /etc/passwd |  head -5
sync:x:4:65534:sync:/bin:/bin/sync
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:102:105::/nonexistent:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

逻辑非

guanwu@master:~/learnshell/awk$ awk -F: '! ($3 +  $4 > 30){print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

控制流

if 只能出现在 BEGIN{}PATTERN{}END{} 中的PATTERN{}中的{}中,即出现在循环体中。

guanwu@master:~/learnshell/awk$ awk -F: '{if($3>$4){print $3 "大于" $4}else{print $3 "小于或等于" $4}}' /etc/passwd | head -5
0小于或等于0
1小于或等于1
2小于或等于2
3小于或等于3
4小于或等于65534
guanwu@master:~/learnshell/awk$ 

if 使用格式:

if(){} : 单分支 
if(){}else{} : 双分支 
if(){}else if(){} else{} : 多分支

for循环

每一行第一个字段打印10次

guanwu@master:~/learnshell/awk$ awk -F: '{for(i=10;i>0;i--){print  NR  " "  $1}}' /etc/passwd |  head -20
1 root
1 root
1 root
1 root
1 root
1 root
1 root
1 root
1 root
1 root
2 daemon
2 daemon
2 daemon
2 daemon
2 daemon
2 daemon
2 daemon
2 daemon
2 daemon
2 daemon
guanwu@master:~/learnshell/awk$ 

while循环 每一行打印10次

guanwu@master:~/learnshell/awk$ awk -F: '{i=1; while(i<=10){print NR " " $0, i++}}' /etc/passwd  | head  -20
1 root:x:0:0:root:/root:/bin/bash 1
1 root:x:0:0:root:/root:/bin/bash 2
1 root:x:0:0:root:/root:/bin/bash 3
1 root:x:0:0:root:/root:/bin/bash 4
1 root:x:0:0:root:/root:/bin/bash 5
1 root:x:0:0:root:/root:/bin/bash 6
1 root:x:0:0:root:/root:/bin/bash 7
1 root:x:0:0:root:/root:/bin/bash 8
1 root:x:0:0:root:/root:/bin/bash 9
1 root:x:0:0:root:/root:/bin/bash 10
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 1
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 2
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 3
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 4
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 5
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 6
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 7
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 8
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 9
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 10
guanwu@master:~/learnshell/awk$ 

do循环

guanwu@master:~/learnshell/awk$ awk 'BEGIN{ 
total=0;
i=0;
do {total+=i;i++;} while(i<=100)
  print total;
}'
5050
guanwu@master:~/learnshell/awk$ 

数组的使用

数组定义


Array[1]="sun"
Array[2]="kai"

Array["first"]="www"
Array"[last"]="name"
Array["birth"]="1987"

数组访问


{ for(item in array) {print array[item]}; }       #输出的顺序是随机的
{ for(i=1;i<=len;i++) {print array[i]}; }         #Len是数组的长度

获取数组的长度

guanwu@master:~/learnshell/awk$ awk 'BEGIN{info="it is a test from asia";lens=split(info,tA," ");print length(tA),lens;}'
6 6
guanwu@master:~/learnshell/awk$ 

对数组进行排序并输出,asort函数是排序函数,并返回数组长度

awk 'BEGIN{info="it is a test from someone";split(info,tA," ");len=asort(tA);for(k in tA){print k,tA[k],"数组长度为" len;}}'

guanwu@master:~/learnshell/awk$ awk 'BEGIN{info="it is a test from someone";split(info,tA," ");len=asort(tA);for(k in tA){print k,tA[k],"数组长度为" len;}}'
1 a 数组长度为6
2 from 数组长度为6
3 is 数组长度为6
4 it 数组长度为6
5 someone 数组长度为6
6 test 数组长度为6
guanwu@master:~/learnshell/awk$ 

for in输出数组

awk 'BEGIN{info="it is a test";tlen=split(info,tA," ");for(k=1;k<=tlen;k++){print k,tA[k];}}'

guanwu@master:~/learnshell/awk$ awk 'BEGIN{info="it is a test";tlen=split(info,tA," ");for(k=1;k<=tlen;k++){print k,tA[k];}}'
1 it
2 is
3 a
4 test
guanwu@master:~/learnshell/awk$ 

实战案例

  1. 选项F的使用,截取第六个字段,并使用":"分割
guanwu@master:~$ tail -l /etc/passwd | awk -F ":" '{print $6}'
/var/lib/geoclue
/run/pulse
/run/gnome-initial-setup/
/run/hplip
/var/lib/gdm3
/home/guanwu
/var/lib/redis
/run/sshd
/run/rpcbind
/var/lib/nfs
guanwu@master:~$ 

打印最后一列的值, NF表示列的字段数量,$NF表示NF列的字段的值

guanwu@master:~/learnshell/awk$ awk  -F ':' '{print $NF}' /etc/passwd |tail  -10
/usr/sbin/nologin
/usr/sbin/nologin
/bin/false
/bin/false
/bin/false
/bin/bash
/usr/sbin/nologin
/usr/sbin/nologin
/usr/sbin/nologin
/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 
  1. -v的使用 统计某列的和
guanwu@master:~/learnshell/awk$ cat test_sum.txt 
1
2
3
4
5
6
7
8
9
10
guanwu@master:~/learnshell/awk$ awk -v "a=0" '{a+=$1;print a}' test_sum.txt  | tail -1
55

传递外部的值

guanwu@master:~/learnshell/awk$ VAR=10000
guanwu@master:~/learnshell/awk$ echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
10000
guanwu@master:~/learnshell/awk$ 
  1. -OFS的使用,指定分隔符并打印
guanwu@master:~/learnshell/awk$ awk -F: 'BEGIN{OFS=" >>> "}{print $NF, $1}' /etc/passwd | tail -5
/bin/bash >>> guanwu
/usr/sbin/nologin >>> redis
/usr/sbin/nologin >>> sshd
/usr/sbin/nologin >>> _rpc
/usr/sbin/nologin >>> statd
guanwu@master:~/learnshell/awk$ 

4.END的使用

打印最后一行

awk 'END{print $0}' /etc/passwd

guanwu@master:~/learnshell/awk$ awk 'END{print $0}' /etc/passwd 
statd:x:132:65534::/var/lib/nfs:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

打印最后一行的字段数

  1. 函数的使用

4.1 格式化打印

awk -F: 'BEGIN{OFS=" | "}{printf "|%+15s|%-15s|\n", $NF, $1}' 

%+15s表示向右对其, %-15s表示向左对其,以 | 为分隔符

guanwu@master:~/learnshell/awk$ awk -F: 'BEGIN{OFS=" | "}{printf "|%+15s|%-15s|\n", $NF, $1}' /etc/passwd |  tail -5
|      /bin/bash|guanwu         |
|/usr/sbin/nologin|redis          |
|/usr/sbin/nologin|sshd           |
|/usr/sbin/nologin|_rpc           |
|/usr/sbin/nologin|statd          |
guanwu@master:~/learnshell/awk$ 
  1. 选行 打印第44行
guanwu@master:~/learnshell/awk$ awk NR==44'{print $0}' /etc/passwd
pulse:x:125:132:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

统计文件的行数

guanwu@master:~/learnshell/awk$ awk 'END{print NR}' test_sum.txt 
10
  1. 定位

6.1 匹配以root开始的行

guanwu@master:~/learnshell/awk$ awk -F: '/^root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
guanwu@master:~/learnshell/awk$ 

使用match函数正则匹配

guanwu@master:~/learnshell/awk$ awk 'BEGIN{info="this is a test2024test!";print match(info,/[0-9]+/)?"ok":"no found";}'
ok
guanwu@master:~/learnshell/awk$ 
  1. 流程 隔五行打印一条直线

awk -F: '{if(NR%5==0){print "----------"}print $0}' /etc/passwd | head -20

guanwu@master:~/learnshell/awk$ awk -F: '{if(NR%5==0){print "----------"}print $0}' /etc/passwd | head -20
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
----------
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
----------
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
----------
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
guanwu@master:~/learnshell/awk$ 

参考

zhuanlan.zhihu.com/p/627048291

www.cnblogs.com/My-IronMan/…

blog.csdn.net/weixin_5827…