linux文本分析awk基础命令介绍(8)

2019-09-23 09:14:39王冬梅

选项-v var=val设定变量

#这里printf函数用法类似C语言同名函数
[root@centos7 ~]# awk -v n=5 'BEGIN{for(i=0;i<n;i++) printf "%02dn",i}' 
00
01
02
03
04
[root@centos7 ~]# 

print等函数还支持使用重定向符>和>>将输出保存至文件

#如按第一列(IP)分类拆分文件access.log,并保存至ip.txt文件中
[root@centos7 temp]# awk '{print > $1".txt"}' access.log 
[root@centos7 temp]# ls -l 172.20.71.*
-rw-r--r-- 1 root root 5297 11月 22 21:33 172.20.71.38.txt
-rw-r--r-- 1 root root 1236 11月 22 21:33 172.20.71.39.txt
-rw-r--r-- 1 root root 4533 11月 22 21:33 172.20.71.84.txt
-rw-r--r-- 1 root root 2328 11月 22 21:33 172.20.71.85.txt

内建函数
length()获得字符串长度

[root@centos7 temp]# awk -F: '{if(length($1)>=16)print}' /etc/passwd 
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
[root@centos7 temp]#

split()将字符串按分隔符分隔,并保存至数组

[root@centos7 temp]# head -1 /etc/passwd|awk '{split($0,arr,/:/);for(i=1;i<=length(arr);i++) print arr[i]}'
root
x
0
0
root
/root
/bin/bash
[root@centos7 temp]# 

getline从输入(可以是管道、另一个文件或当前文件的下一行)中获得记录,赋值给变量或重置某些环境变量

#从shell命令date中通过管道获得当前的小时数
[root@centos7 temp]# awk 'BEGIN{"date"|getline;split($5,arr,/:/);print arr[1]}'
09
#从文件中获取,此时会覆盖当前的$0。(注意逐行处理b.txt的同时也在逐行从c.txt中获得记录并覆盖$0,当getline先遇到eof时<即c.txt文件行数较少>将输出空行)
[root@centos7 temp]# awk '{getline <"c.txt";print $4}' b.txt 
"https://segmentfault.com/blog/learnning"
[root@centos7 temp]# 
#赋值给变量
[root@centos7 temp]# awk '{getline blog <"c.txt";print $0"n"blog}' b.txt 
aasdasdadsad
BLOG ADDRESS IS "https://segmentfault.com/blog/learnning"
[root@centos7 temp]# 
#读取下一行(也会覆盖当前$0)
[root@centos7 temp]# cat file
anny
100
bob
150
cindy
120
[root@centos7 temp]# awk '{getline;total+=$0}END{print total}' file
370
#此时表示只对偶数行进行处理

next作用和getline类似,也是读取下一行并覆盖$0,区别是next执行后,其后的命令不再执行,而是读取下一行从头再执行。

#跳过以a-s开头的行,统计行数,打印最终结果
[root@centos7 temp]# awk '/^[a-s]/{next}{count++}END{print count}' /etc/passwd
2
[root@centos7 temp]# 
#又如合并相同列的两个文件
[root@centos7 temp]# cat f.txt 
学号 分值
00001 80
00002 75
00003 90
[root@centos7 temp]# cat e.txt 
姓名 学号
张三 00001
李四 00002
王五 00003
[root@centos7 temp]# awk 'NR==FNR{a[$1]=$2;next}{print $0,a[$2]}' f.txt e.txt  
姓名 学号 分值
张三 00001 80
李四 00002 75
王五 00003 90
#这里当读第一个文件时NR==FNR成立,执行a[$1]=$2,然后next忽略后面的。读取第二个文件时,NR==FNR不成立,执行后面的打印命令