awk命令

语法格式

awk [参数] [处理内容] [操作对象]

常用命令选项

-F fs:fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value:赋值一个用户定义变量,将外部变量传递给awk
-f scripfile:从脚本文件中读取awk命令

内置变量

  • FS :输入字段分隔符,默认为空白字符
  • OFS :输出字段分隔符,默认为空白字符
  • RS :输入记录分隔符,指定输入时的换行符,原换行符仍有效
  • ORS :输出记录分隔符,输出时用指定符号代替换行符
  • NF :字段数量,共有多少字段, $ NF引用最后一列,$(NF-1)引用倒数第2列
  • NR :行号,后可跟多个文件,第二个文件行号继续从第一个文件最后行号开始
  • FNR :各文件分别计数, 行号,后跟一个文件和NR一样,跟多个文件,第二个文件行号从1开始
  • FILENAME :当前文件名
  • ARGC :命令行参数的个数
  • ARGV :数组,保存的是命令行所给定的各参数,查看参数

演示
OFS——指定输出分隔符
在awkdemo文件中,字段之间的分隔符是空格,使用OFS,指定输出的分隔符为—

[root@bogon ~]# cat awkdemo
hello world
[root@bogon ~]# awk -v FS=' ' -v OFS='---' '{print $1,$2}' awkdemo
hello---world

FNR——统计文件行数

 [root@bogon ~]# awk '{print FNR}' awkdemo
1
[root@bogon ~]# vi awkdemo
hello world
sdassasad
dasdkqjwlk
nzxhcozxjhclk
dnaskjdnsa
[root@bogon ~]# awk '{print FNR}' awkdemo
1
2
3
4
5

awk PATTERN匹配

格式:
PATTERN:根据pattern 条件,过滤匹配的行,再做处理

(1)如果未指定:空模式,匹配每一行

(2)/regular expression/ :仅处理能够模式匹配到的行,正则,需要用/ / 括起来

(3)relational expression:关系表达式,结果为“真”才会被处理

真:结果为非0值,非空字符串

假:结果为空字符串或0值

(4)line ranges:行范围

startline(起始行),endline(结束行):/pat1/,/pat2/ 不支持直接给出数字,可以有多段,中间可以有间隔

(5)BEGIN/END 模式

BEGIN{}: 仅在开始处理文件中的文本之前执行一次

END{} :仅在文本处理完成之后执行

演示:
打印awkdemo文件中的第一个字段

[root@bogon ~]# cat awkdemo
hello world
linux:sentos
[root@bogon ~]# awk -F: '{print $1}' awkdemo
hello world
linux

在执行文件中的文本内容之前执行代码 BEGIN{print “第一列”}
执行之后执行 END{print “结束”}’

[root@bogon ~]# awk -F: 'BEGIN{print "第一列"}{print $1} END{print "结束"}' awkdmo
第一列
hello world
linux
结束

awk控制语句—if-else判断:
语法:

if(condition){statement;…}[else statement]  双分支
if(condition1){statement1}else if(condition2){statement2}else{statement3}  多分支
对/etc/passwd文件中第三个字段进行条件判断,打印第一,第三个字段
[root@bogon ~]# awk -F: '{if($3>10 && $3<1000)print $1,$3}' /etc/passwd
operator 11
games 12
ftp 14
nobody 99
systemd-network 192
dbus 81
polkitd 999
sshd 74
postfix 89

awk控制语句—while循环:
语法:

while``(condition){statement;…}

以:为分隔,显示每一行的长度大于6的单词和其长度

[root@bogon ~]# awk -F: '{i=1;while(i<=NF) {if(length($i)>=6){print $i,length($i)}; i++}}' awkdemo
hello world 11
sentos 6
redhat 6

案例:筛选给定时间范围内的日志

grep/sed/awk用正则去筛选日志时,如果要精确到小时、分钟、秒,则非常难以实现。

但是awk提供了mktime()函数,它可以将时间转换成epoch时间值。epoch值是数值,可以用来比较大小

awk 'BEGIN{print mktime("2019 11 10 03 42 40")}'
 BEGIN{
  which_time = mktime("2019 11 10 03 42 40")
}

{
  match($0,"^.*\\[(.*)\\].*,arr")  //取出日志中的字符串
  tmp_time = strptime1(arr[1])  //将字符串转换为epoch值

  if(tmp_time > which_time){print} //通过epoch值来比较大小
}

functiom steptime1(str,arr,Y,M,D,h,m,s){
  patsplit(str,arr,"[0-9]{1,4}")
  Y=arr[1]
  M=arr[2]
  D=arr[3]
  h=arr[4]
  m=arr[5]
  s=arr[6]
  return mktime(sprintf(%s %s %s %s %s %s,Y,M,D,h,m,s))
}

构建时间字符串格式
部分日志时间可能出现,月份为英文的情况因为英文部分无法比较大小,需要将月份为英文的字段转换为数字,进行比较

function strptime2(str,dt_str,arr,Y,M,D,H,m,S) {
  dt_str = gensub("[/:+]"," ","g",str)
  # dt_sr = "10 Nov 2019 23 53 44 08 00"
  split(dt_str,arr," ")
  Y=arr[3]
  M=mon_map(arr[2])
  D=arr[1]
  H=arr[4]
  m=arr[5]
  S=arr[6]
  return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))
}

function mon_map(str,mons){
  mons["Jan"]=1
  mons["Feb"]=2
  mons["Mar"]=3
  mons["Apr"]=4
  mons["May"]=5
  mons["Jun"]=6
  mons["Jul"]=7
  mons["Aug"]=8
  mons["Sep"]=9
  mons["Oct"]=10
  mons["Nov"]=11
  mons["Dec"]=12
  return mons[str]
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值