awk笔记整理

awk介绍

awk:报告生成器,格式化文本输出。有多种版本:New awk(nawk),GNU awk(gawk)。CentOS中使用的是gawk
gawk:模式扫描和处理语言

awk基本用法

awk程序可由:BEGIN语句块、能够使用模式匹配的通用语句块(program)、END语句块,共3部分组成 pragram通常是被放在单引号中
常用选项:
-F "分隔符" 指明输入时用到的字段分隔符,如果不指定分隔符,默认以空格分隔
-V var=value 变量赋值

awk变量

awk变量有内置和自定义变量
常用内置变量:
变量名 | 作用
$0 | 表示一整行 |
$1-$n | 表示第一个字段到第n个字段 |
FS | 输入字段分隔符,默认为空白字符 |
OFS | 输出字段分隔符,默认为空白字符 |
RS | 输入记录分隔符,指定输入时的换行符 |
ORS | 输出记录分隔符,指定输出时的换行符 |
NF | 字段数量 |
NR | 记录号 |
FNR | 各文件分别记数,记录号 |
FILENAME | 当前处理文件的文件名 |
ARGC|命令行参数的个数,awk算第一个参数,中间语句不算参数 |
ARGV|数组,保存的是命令午所给定的各参数|

[root@CentOS7 data]#awk 'BEGIN{print ARGV[0] }' /etc/fstab
awk
[root@CentOS7 data]#awk 'BEGIN{print ARGV[1] }' /etc/fstab
/etc/fstab

自定义变量(区分字符大小写)

[root@CentOS7 data]#awk -v test='hello gawk' '{print test}' /etc/fstab
hello gawk
.
.
.
hello gawk
[root@CentOS7 data]#awk -v test='hello gawk' 'BEGIN{print test}'
hello gawk
[root@CentOS7 data]#awk 'BEGIN{test="hello,gawk";print test}'
hello,gawk

awk格式化

printf命令
格式化输出:print "FORMAT",item1,item2...

1、必须指定FORMAT
2、不会自动换行,需要显式给出换行控制符,\n
3、FORMAT中需要分别为后面第个item指定格式符
格式符:与item一一对应
%c:显示字符的ASCII码
%d,%i:显示十进制整数
%e,%E:显示科学计数法数值
%f:显示为浮点数
%g,%G以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%

修饰符
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后数度,%3.1f表示显示到小数点后一位

awk操作符

算术操作符

+、-、*、/、^、% 加减乘除乘取余
-x:转换为负数
+x:将字符串转换为数值

字符串操作符:没有符号的操作符,字符串连接
赋值操作符

=,+=,-=,*=,/=,%=,^=,++,--

比较操作符

==,!=,>,>=,<,<=

模式匹配符:

~:左边是否和右边匹配,包含
!~: 是否不匹配

逻辑操作符:与&&,或||,非!
条件表达式(三目表达式)
selector?if-true-expression:if-false-expression
如果selector 为真,执行if-true部分,为假,执行if-false部分

awk条件判断

根据模式(pattern)条件,过滤匹配的行,再做处理

如果未指定:空模式,匹配第一行

/regular expression/ :仅处理能够与模式相匹配的行,需要用//括起来

[root@CentOS7 data]#awk '/^UUID/{print $1}' /etc/fstab
UUID=95730fd4-d3a2-4af9-8311-46422db2ed23
UUID=8ea0b7b5-109d-43b7-bd1a-f18c5f4ae5de
UUID=f6d8e5da-09bf-480a-9089-a83d8cb674c5
UUID=74df8071-4517-4645-872e-976e8a5514e4

表示只显示以UUID开头的行的第一个字段

relational expression:关系表达式,结果为"真"才会实处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值

line ranges:行范围 表示从哪行开始,到哪行结束
startline,endline:/pat1/,/pat2/不支持直接给出数字格式
示例:表示从以root开始的行,到以nobody开始的行

[root@CentOS7 data]#awk '/^root/,/^nobody/{print $1}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
.
.
.
nobody:x:99:99:Nobody:/:/sbin/nologin
[root@CentOS7 data]#

BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次

[root@CentOS7 data]#awk -F: 'BEGIN{print "USER USERID"}{print $1 ":" $3}END{print "END FILE"}' /etc/passwd
USER USERID
root:0
.
.
.
END FILE

awk循环

if-else语句
语法:if(条件){statement;...}[else statement]
if(){}else if(){}else{}
使用场景:对awk取得的整行或某个字段做条件判断
示例:显示ID大于等于1000的行的第一,第3字段

[root@CentOS7 data]#awk -F: '{if($3&gt;=1000)print $1,$3}' /etc/passwd
nfsnobody 65534
liuqiyou 1000
[root@CentOS7 data]#awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd
root
liuqiyou
[root@CentOS7 data]#awk -F: '{if($3&gt;=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}'
/etc/passwd
root or Sysuser: root
.
.
.
root or Sysuser: tcpdump
Common user: liuqiyou
[root@CentOS7 data]#awk 'BEGIN{test=100;if(test&gt;90){print "very good "}else if(test&gt;60){print " goood"}else{print "no pass"}}'
very good

while 循环
语法:while(条件){动作}
条件"真",进入循环;条件"假",退出循环
使用场景:
对一行内的多个字段逐一处理时使用
对数组中的各元素 逐一处理时使用
示例:

[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{i=1;while(i&lt;=NF){print $i,length($i);i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-957.el7.x86_64 30
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
[root@CentOS7 data]#awk 'BEGIN{i=1;sum=0;while(i&lt;=100){sum+=i;i++}print sum}'
5050

do-while循环
语法:do{}while()
先执行一次循环体后做条件判断,最少执行一次

[root@CentOS7 data]#awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i&lt;=100);print total}'
5050

for循环
语法:for(i=0;i<=100;i++){动作}
特殊用法:遍历数组是的元素
for(i in array){print i,array[i]}

[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{for(i=1;i&lt;=NF;i++){print $i,length($i)}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-957.el7.x86_64 30
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
[root@CentOS7 data]#awk 'BEGIN{for(i=1;i&lt;=100;i++)sum+=i;print sum}'
5050

switch语句
语法:switch(expression){case VALUE1 or /PEGEXP/:statement1;case VALUE2 or /REGEXP2/}

break和continue
break 跳出整个循环,提前结束循环

[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i&lt;=100;i++){if(i==66)break;sum+=i}print sum}'
2145

continue 跳出本次循环,进入下一次循环

[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i&lt;=100;i++){if(i%2==0)continue;sum+=i}print sum}'
2500

next:跳出本行循环,进入下一行循环

awk数组

关联数组:array[index-expession]
index-expession:

1、可使用任意字符串;字符串要使用双引号括起来
2、如果某数组元素事先不存在,在引用 时,awk会自动创建些元素,并将其值初始化为"空串"
3、若要判断数组中是否存在某元素,要使用"index in array"格式进行遍历

[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
Monday
[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}'
Tuesday

去除重复的行

[root@CentOS7 data]#awk '{!line[$0]++;print $0,line[$0]}' /etc/passwd

使用for循环遍历数组中的每个元素
for(var in array){for-body}
var会遍历arrayr的每个索引

[root@CentOS7 data]#netstat -tan |awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}'
LISTEN 9
ESTABLISHED 1
[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print i,weekd
asys[i]}}'
tue
mon

awk函数

数值处理:

rand():返回0到1之间一个随机数
awk 'BEGIN{STAND();for(i=1;i&lt;=10;i++)print int(rand()*100)}'

字符串处理:
length([s]):返回指定字符串的长度

[root@CentOS7 data]#awk -F: '{print length($0)}' /etc/passwd

sub(r,s,[t]):对t字符串搜索r表示的模式匹配的内容,并全部替换为s所表示的内容

[root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'sub(/:/,"-",$1)'
2008-08:08 08:08:08

gsub(r,s[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容

[root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'gsub(/:/,"-",$1)'
2008-08-08 08:08:08
[root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'gsub(/:/,"-",$0)'
2008-08-08 08-08-08

split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存到array所表示的数组中,第一个索引值为1,第二个索引值为2,...

[root@CentOS7 data]#netstat -tn | awk '/^tcp\&gt;/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
172.22.37.100 1

自定义函数
自定义函数格式

function name ( parameter, parameter, ... ) {
  statements
  return expression
}

调用系统命令

awk中调用shell命令

system命令
空格是awk中的字符串连接符,如果system中需要使用awk中的变量,可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来

[root@CentOS7 data]#awk 'BEGIN{system("hostname")}'
CentOS7.localdomain
[root@CentOS7 data]#awk 'BEGIN{score=100;system("echo your scores is "score)}'
your scores is 100

awk脚本

将awk程序写成脚本,直接调用或执行

[root@CentOS7 data]#vim f1.awk
#!/bin/awk
{if($3>=1000)print $1,$3}
[root@CentOS7 data]#awk -F: -f f1.awk /etc/passwd
nfsnobody 65534
liuqiyou 1000 
[root@CentOS7 data]#vim f2.awk
#!/bin/awk -f
#this is a awk script
{if($3>=1000)print $1,$3}
[root@CentOS7 data]#chmod +x f2.awk
[root@CentOS7 data]#./f2.awk -F: /etc/passwd
nfsnobody 65534
liuqiyou 1000

向awk脚本传递参数

格式:awkfile var=value var2=value2...inputfile
注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以能完-v参数,让awk在执行BEGIN之前得到变量的值。命令行每一个指定的变量都要一个-v参数

[root@CentOS7 data]#vim test.awk
#!/bin/awk -f
{if($3>=min && $3<=max)print $1,$3}
[root@CentOS7 data]#chmod +x test.awk
[root@CentOS7 data]#./test.awk -F: min=100 max=200 /etc/passwd
systemd-network 192
abrt 173
rtkit 172
pulse 171
qemu 107
usbmuxd 113

猜你喜欢

转载自blog.51cto.com/13749470/2378522