二十二 awk命令

一、awk和sed的区别

awk更像是脚本语言
awk用于“比较规范”的文本处理,用于统计数量并输出指定字段
使用sed将不规范的文本,处理为“比较规范”的文本

二、awk脚本的流程控制

输入数据前例程 BEGIN{}
主输入循环{}
所有文件读取完成例程END{}

三、awk的字段引用和分离

记录和字段

  • 每行称作awk的记录
  • 默认使用空格、制表符分隔开的单词称作字段
  • 可以自己制定分割的字段

1 字段的引用

awk中使用$1 $2 ... $n表示每一个字段

  • awk '{print $1,$2,$3}' filename

awk可以使用 -F 选项改变字段分隔符

  • awk -F ',' '{print $1,$2,$3}' filename
  • 分隔符可以使用正则表达式
--- ~ »cat log.txt
2020-05-05 00:01:10.922|INFO|13087:140628635487280|logger.py:80|logger._log|14062863548728
015886080709221959|14062863548728015886080709221959|##BEGIN####0##url##{}##None##None##GET##10.229.99.82##1588608070##
2020-05-05 00:01:10.923|INFO|13087:140628635487280|logger.py:80|logger._log|14062863548728
015886080709221959|14062863548728015886080709221959|##END##0####1##url##{}##200##{}##GET##10.229.99.82##1588608070##
# 以‘2020-05-05’为开头的行,按空格分隔后,取第一个字段
--- ~ » awk -F " " '/^2020-05-05/{print $1}' log.txt
2020-05-05
2020-05-05
# 输出行号,x变量没有初始值,默认初始化值为0
--- ~ » awk -F " " '/^2020-05-05/{print x++,$1}' log.txt
0 2020-05-05
1 2020-05-05

1 awk '$4~/xxx/'字段匹配:匹配第四个字段是xxx的行

Administrator@PC-20141114NHWZ MINGW64 /e/shell/file_folder
$ awk '$4~/version/' url.log
HTTP 200 https://github.com/discourse/discourse version cd5b7109d04722df5c39b2ded9fa4ead6c290ce4

2 awk '$4!~/xxx/'字段匹配:匹配第四个字段不是xxx的行

Administrator@PC-20141114NHWZ MINGW64 /e/shell/file_folder
$ awk '$4!~/version/' url.log

3 找到匹配的行后,只输出第N个字段

Administrator@PC-20141114NHWZ MINGW64 /e/shell/file_folder
$ awk '$4~/version/{print $4}' url.log
version

四、awk的表达式

  • 赋值操作符
  • 算数操作符
  • 系统变量
  • 关系操作符
  • 布尔操作符

1 赋值操作符

= 是最常用的赋值操作符

  • var1 = "name"
  • var2 = "hello" "world"
  • var3 = $1

其他赋值操作符

  • ++ -- += -= *= /= %= ^=

2 算数操作符

算数操作符 + - * / % ^

3 系统变量

FS和OFS字段分隔符,FS为输入的字段分隔符,OFS表示输出的字段分隔符
RS记录分隔符
NR和FNR行数
NF字段数量,最后一个字段内容可以用$NF取出

(1) FS输入的字段分隔符

--- ~ » head -5 /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
sync:x:4:65534:sync:/bin:/bin/sync
# 此处设置分隔符为‘:’,其实就是改变了系统变量
--- ~ »head -5 /etc/passwd | awk -F ':' '{print $1}'
root
daemon
bin
sys
sync
# 也可以直接在输入数据前,在BEGIN里面给FS系统变量赋值
--- ~ » head -5 /etc/passwd | awk 'BEGIN{FS=":"}{print $1}'
root
daemon
bin
sys
sync

(2) OFS表示输出的字段分隔符

# 默认的输出分隔符是空格
--- ~ » head -5 /etc/passwd | awk 'BEGIN{FS=":"}{print $1,$2}'
root x
daemon x
bin x
sys x
sync x
# 使用OFS系统变量指定输出分隔符,输出所有行是$2
--- ~ » head -5 /etc/passwd | awk 'BEGIN{FS=":";OFS=","}{print $1,$2}'
root,x
daemon,x
bin,x
sys,x
sync,x

(3) RS记录分隔符:默认是以\n作为每行的分隔符,可以通过RS制定行分隔符

--- ~ » head -2 /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# 默认以\n作为行分隔符的标识
--- ~ » head -2 /etc/passwd | awk -F ':' '{print $0}'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# 指定以':'作为行分隔符的标识
--- ~ » head -2 /etc/passwd | awk -F ':' 'BEGIN{RS=":"}{print $0}'
root
x
0
0
root
/root
/bin/bash
daemon
x
1
1
daemon
/usr/sbin
/usr/sbin/nologin

(4) NR和FNR行数

# NR和FNR都可以显示行号
--- ~ »head -2 /etc/passwd | awk '{print NR,$0}'
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
--- ~ » head -2 /etc/passwd | awk '{print FNR,$0}'
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

NR和FNR区别如下:

(5) NF 字段的数量

# NF指每行总共有多少个字段
--- ~ » head -5 /etc/passwd | awk 'BEGIN{FS=":"}{print NF}'
7
7
7
7
7
# $NF指输出最后一个字段
--- ~ »  head -5 /etc/passwd | awk 'BEGIN{FS=":"}{print $NF}'
/bin/bash
/usr/sbin/nologin
/usr/sbin/nologin
/usr/sbin/nologin
/bin/sync

4 关系操作符

< > <= >= == !=

5 布尔操作符

&&  ||   !

五、awk判断和循环

1 条件语句

条件语句使用计开头,根据表达式的结果来判断执行移条语句
 if(表达式)
 awk语句1
 [
  else
  awk语句2
 ]
如果有多个语句需要执行可以使用{}将多个语句括起来

# 输出第二列大于等于80的用户名
--- ~/shell_practice » awk '{if($2>=80) print $1}' kpi.txt                                            
user2
user4
--- ~/shell_practice » awk '{if($2>=80) { print $1;print $2}}' kpi.txt
user2
80
user4
90

2 循环语句

  • while循环
     while(表达式)
      awk语句1
  • do 循环
     do {
      awk 语句1
    } while (表达式)
  • for 循环
     for (初始值;循环判断条件;累加)
      awk语句1
  • 影响控制的其他语句
     break
     continue
--- ~/shell_practice » cat kpi.txt
user1 70 72 74 76 74 72
user2 80 82 84 82 80 78
user3 60 61 62 63 64 65
user4 90 89 88 87 86 85
user5 45 60 63 62 61 50
# 求出第一行的平均值
--- ~/shell_practice » head -1 kpi.txt| awk '{for(c=2;c<=NF;c++) sum = sum+$c;print sum/(NF-1)}'
73
# 求出每一行的平均值
--- ~/shell_practice » awk '{sum=0;for(c=2;c<=NF;c++) sum = sum+$c;print sum/(NF-1)}' kpi.txt
73
81
62.5
87.5
56.8333

六 awk的数组

  • 数组的定义
  • 数组的遍历
  • 删除数组
  • 命令行参数数组

1 数组的定义

数组:一组有某种关联的数据(变量),通过下标依次访问

  • 数组名[下标] = 值
  • 下标可以使用数字也可以使用字符串

2 数组的遍历

for(变量 in 数组名)

  • 使用 数组名[变量]的方式依次对每个数组的元素进行操作
--- ~/shell_practice » awk '{sum=0;for(c=2;c<=NF;c++) sum = sum+$c;avg[$1]=sum/(NF-1)}END{for (user in avg) print user,avg[user]}' kpi.txt
user1 73
user2 81
user3 62.5
user4 87.5
user5 56.8333

3 删除数组

删除数组

  • delete 数组[下标]

4 命令行参数数组

命令行参数数组

  • ARGC
  • ARGV

你可能感兴趣的:(二十二 awk命令)