Linux文本三剑客之awk

目录

前言

awk

1.认识awk

2.使用awk

2.1语法

2.2常用命令选项

2.3awk变量

2.3.1内置变量

2.3.2自定义变量

2.4printf命令

awk例题


前言

        awk、grep、sed是linux操作文本的三大利器,合称文本三剑客,也是必须掌握的linux命令之一。三者的功能都是处理文本,但侧重点各不相同,其中属awk功能最强大,但也最复杂。grep更适合单纯的查找或匹配文本,sed更适合编辑匹配到的文本,awk更适合格式化文本,对文本进行较复杂格式处理。此篇主要讲解三剑客中的awk。

awk

1.认识awk

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

2.使用awk

2.1语法

awk  [options] 'pattern { action }' file

 这里'options'是指常用命令选项,可选可不选,'patten'是用于匹配文本的格式,'action'是指匹配到格式时执行的动作,'file'指的是所要处理的文件。

2.2常用命令选项

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

2.3awk变量

变量:内置和自定义变量,每个变量前加-v命令选项

2.3.1内置变量

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

2.3.2自定义变量

(1)-v var=value

① 先定义变量,后执行后动作print

[root@along ~]# awk -v name="along" -F: '{print name":"$0}' awkdemo
along:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you

 ② 在执行动作print后定义变量

[root@along ~]# awk -F: '{print name":"$0;name="along"}' awkdemo
:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you

(2)在 program中直接定义

可以把执行的动作放在脚本中,直接调用脚本-f

[root@along ~]# cat awk.txt
{name="along";print name,$1}
[root@along ~]# awk -F: -f awk.txt awkdemo
along hello
along linux
along along

2.4printf命令

比print更强大

2.4.1格式

(1)格式化输出

 printf` `"FORMAT"``, item1,item2, ...

① 必须指定FORMAT

不会自动换行,需要显式给出换行控制符,\n

③ FORMAT 中需要分别为后面每个item 指定格式符

(2)格式化:与item对应

  • %c:显示字符的ASCII码
  • %d,%i:显示十进制数
  • %e,%E:显示科学计数法数值
  • %f:显示为浮点数,小数
  • %g,%G:以科学计数法或浮点形式显示数值
  • %s:显示字符串
  • %u:无符号整数
  • %%: 显示%自身

(3)修饰符:%c[/d/e/f...]之间

  • #[.#]:第一个数字控制显示的宽度;第二个#号表示小数点后的精度
  • -:左对齐(默认右对齐)
  • +:显示熟知的正负符号

awk例题

题:筛选给定范围内的日志写出来(如筛选出2023-08-06 22:20:00之后的日志)

解题步骤:

创建一个脚本文件,进行条件筛选

BEGIN{
  # 要筛选什么时间的日志,将其时间构建成epoch值
  which_time = mktime("2023 08 06 22 20 00")
}

{
  # 取出日志中的日期时间字符串部分
  match($0,"^.*\\[(.*)\\].*",arr)
  
  # 将日期时间字符串转换为epoch值
  tmp_time = strptime2(arr[1])
  
  # 通过比较epoch值来比较时间大小
  if(tmp_time > which_time){
    print 
  }
}

# 构建的时间字符串格式为:"10/Nov/2019:23:53:44+08:00"
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]
}

使用awk命令, 使用-f选项,选择对应的日志文件

awk -f filter_logs.awk /var/log/apache/access.log

结果:

 

你可能感兴趣的:(linux,运维,服务器)