awk 简单整理

在这里插入图片描述

1. 概念

awk是一种专门为文本处理设计的编程语言,它是Linux和Unix环境中功能强大的数据处理引擎之一。awk的名称来源于其创始人阿尔佛雷德·艾侯(Alfred Aho)、彼得·温伯格(Peter Weinberger)和布莱恩·柯林汉(Brian Kernighan)姓氏的首个字母。

awk的工作原理是逐行读取文本,默认以空格或Tab键为分隔符进行分隔,将分隔所得的各个字段保存到内置变量中,并按模式或条件执行编辑命令。awk提供了强大的功能,包括样式装入、流控制、数学运算、进程控制语句以及内置的变量和函数。

awk的语法格式基本为“awk 选项 ‘模式或条件 {操作}’ 文件1 文件2”,还可以使用脚本文件或命令行参数来执行。awk中常用的内置变量包括FS(字段分隔符)、OFS(输出分隔符)、RS(行分隔符)、NF(字段数量)、NR(行号)、FNR(与NR相对,当读取多个文件时用于区分文件)、(当前行的整行内容)和(当前行的整行内容)和n(当前行的第n个字段)。

awk可以用于数据统计、文本过滤、报告生成等多种任务,其输入可以来自标准输入、文件或管道。awk还支持逻辑操作符(如&&、||、!),简单的数学运算和流程控制语句。在awk中,模式和操作可以单独使用,也可以组合使用,以实现复杂的文本处理需求。

总的来说,awk是一个功能强大的文本处理工具,广泛应用于数据分析和报告生成等领域。它通过其独特的语法和内置功能,使得复杂的文本处理任务变得相对简单。

2. awk

命令结构

awk 'BEGIN{commands} pattern{command} END{command}'

awk工作原理

  • 第一步:执行BEGIN{action}语句块中的语句,该语句块不依赖于文件,awk在执行是将在读取文件之前执行该语句中的语句块,常用语变量的初始化,打印输出表格的表头。
  • 第二步:从文件、标准输入、上一条命令输出结果输入到一行,然后进行pattern{command}语句块,它将逐行扫描文件,从第一行到最后一行。若没有提供pattern语句,则默认执行打印{print},即打印每一个读取到的行。
  • 第三步:当读至文件最后时,执行END{action}语句块。通常用于汇总在pattern语句中执行的过程

下面我们来学习这个命令的使用

2.1 基本用法

awk [options] '[条件类型] 1{动作 1} 条件类型 2{动作 2} ...' filename

选项类型:

  • -F[]:指明输入字段分隔符;默认以空白为分隔符。例如-F[,],以逗号为分隔符
  • -v var=value:变量赋值,无须声明,可直接调用
  • -f /path/awk_script:从awk脚本文件读取条件

条件类型:
后续展开介绍

常用动作:

  • print:print在显示多个结果的时候以逗号分隔,结果将这几部分的内容自动使用输出分隔符(字段输出分割符默认是空格,记录输出分割符默认是换行符)进行分隔,且不需要添加换行符`\n;如果不使用,间隔,则打印时会连在一起,即使使用了空格
  • printf:printf可以更加灵活的控制某一个字段的输出格式,通过使用诸如%-12s,%3.1f等格式化方法。printf更加接近使用C语言的同学的习惯
#-F 
[root@node-249 test]# awk -F[:] '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
...

#-v
[root@node-249 test]# awk -F[:] -v f1=1 -v f2=3  '{print $f1,$f2}' /etc/passwd
root 0
bin 1
...

#-F []可缺省
[root@node-249 test]# awk -F: -v f1=1 -v f2=3  '{print $f1,$f2}' /etc/passwd
root 0
bin 1
daemon 2
...
[root@node-249 test]# last -n 5|awk '{print $1,$3 }'
root 10.0.82.22
root 192.168.115.1
root 10.0.82.22
root Tue
reboot boot

wtmp Thu
[root@node-249 test]# last -n 5|awk '{print $1 "\t" $3 }'
root    10.0.82.22
root    192.168.115.1
root    10.0.82.22
root    Tue
reboot  boot

wtmp    Thu
[root@node-249 test]# last -n 5|awk '{printf("%s,%s\n",$1,$3)}'
root,10.0.82.22
root,192.168.115.1
root,10.0.82.22
root,Tue
reboot,boot
,
wtmp,Thu
[root@node-249 test]# cat awk.script
{print $1,$3}
[root@node-249 test]# awk -f awk.script -F: /etc/passwd
root 0
bin 1
daemon 2

awk 后面接两个单引号并加上大括号 {} 来设定想要对数据进行的处理动作。 awk 可以处理后续接的文件,也可以读取来自前个指令的 standard output 。 但如前面说的, awk 主要是处理『每一行的字段内的数据』,而默认的『字段的分隔符为 “空格键” 或 “[tab]键” 』!

2.2 变量

内置变量

变量名说明
$0表示整个输入记录。
$n表示输入记录的第n个字段。
NF表示字段数量变量,在处理记录时,它表示当前记录的字段数。
NR表示记录的数量变量,在处理文件时,它表示当前处理的是第几行。
FS表示字段分隔符,默认是空格或Tab。
OFS表示输出字段分隔符,默认也是空格。
FILENAME表示当前输入文件的名字。
RS表示记录分隔符,用于定义输入时的换行符,默认是换行符
ORS表示输出记录分隔符,用于定义输出时的换行符,默认也是换行符
ARGC命令行参数数量
ARGV命令行参数属组

注意:在 awk 内的 NR, NF 等变量要用大写,且不需要有钱字号 $

[root@node-249 test]# awk -F: '{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...
[root@node-249 test]# awk -F: '{print $1}' /etc/passwd
root
bin
daemon
...
[root@node-249 test]# awk -F: '{print NF}' /etc/passwd
7
7
7
...
[root@node-249 test]# awk -F: '{print NR,$1}' /etc/passwd
1 root
2 bin
3 daemon
[root@node-249 test]# awk -v FS=":" '{print $1,$3}' /etc/passwd|head -3
root 0
bin 1
daemon 2
[root@node-249 test]# awk -F: '{print $1,$3}' /etc/passwd|head -3
root 0
bin 1
daemon 2
[root@node-249 test]# awk -F: -v OFS="#" '{print $1,$3}' /etc/passwd|head -3
root#0
bin#1
daemon#2
[root@node-249 test]# awk -F: -v OFS="#" '{print $0,FILENAME}' /etc/passwd|head -3
root:x:0:0:root:/root:/bin/bash#/etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin#/etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin#/etc/passwd
[root@node-249 test]# awk  -v RS=":" '{print $0}' /etc/passwd|head -3
root
x
0
[root@node-249 test]# awk  -v FS=":" -v ORS="#" '{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash#bin:x:1:1:bin:/bin:/sbin/nologin#daemon:x:2:2:daemon:/sbin:/sbin/nologin#adm:x:3:4:adm:/var/adm:/sbin/nologin#lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin#sync:x:5:0:sync:/sbin:...

[root@node-249 test]# awk  -v FS=":"  '{print ARGC}' /etc/passwd|head -3
2
2
2
[root@node-249 test]# awk  -v FS=":"  '{print ARGV[1]}' /etc/passwd|head -3
/etc/passwd
/etc/passwd
/etc/passwd
[root@node-249 test]# awk  -v FS=":"  '{print ARGV[0]}' /etc/passwd|head -3
awk
awk
awk

外置变量(自定义变量)
在awk命令中,我们可以使用-v选项设置一个外置变量,这个变量可以在awk程序中使用
定义方法:

  • -v varName=value
[root@node-249 ~]# awk -v myVar="$var" 'BEGIN{print myVar}'
hello

[root@node-249 ~]# awk -v myVar="$var" 'BEGIN{print "\""myVar"\""}'
"hello"

2.3 执行流程

awk 'BEGIN{commands} pattern{command} END{command}'
  • 读取输入文件之前执行的代码段(由关键字BEGIN标识)
  • 主循环执行输入文件的代码段
  • 读取输入文件之后的代码段(由关键字END标识)
执行顺序简述:
1. BEGIN{}	: 最开始执行
2. //		: 正则
3. {}		: 循环体
4. END{}	: 最后执行

这里面最少有一个,最多有四个!

一个比较完整的示例语句

[root@node-249 ~]# cat /etc/passwd|awk 'BEGIN {FS=":";print "begin content"} $3<100{print $1,$3,$6} END{print "end content"}'
begin content
root 0 /root
bin 1 /bin
daemon 2 /sbin
...
ntp 38 /etc/ntp
end content

awk语句简解:
5. 首先执行BEGIN {FS=":";print "begin content"},其中定义了分隔符为:,打印begin content
6. 执行正则表达式$3<100,确认从/etc/passwd中获取的每行内容的第三段(即UID)小于100的满足条件
7. 执行循环体{print $1,$3,$6},打印第一、三、六段内容
8. 所有循环结束,执行END{print "end content"},打印end content

2.4 BEGIN模块

  • 第一个作用,内置变量定义
[root@node-249 ~]# ip a show dev ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:39:d0:a6 brd ff:ff:ff:ff:ff:ff
    inet 10.0.82.254/24 brd 10.0.82.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe39:d0a6/64 scope link
       valid_lft forever preferred_lft forever
[root@node-249 ~]# ip a show dev ens33|awk 'BEGIN{FS="inet |/24"} NR==3{print $2}'
10.0.82.254
[root@node-249 ~]# ip a show dev ens33|awk 'BEGIN{FS="[ /]+"} NR==3{print $3}'
10.0.82.254
[root@node-249 ~]# ip a show dev ens33|awk 'BEGIN{FS="[^0-9.]+"} NR==3{print $2}'
10.0.82.254
  • 第二个作用,读取文件之前,输出提示性信息(例如,表头)
[root@node-249 ~]# awk -F: 'BEGIN{print "username","UID"}{print $1,$3}' /etc/passwd |head -5
username UID
root 0
bin 1
daemon 2
adm 3
  • 第三个作用,使用BEGIN模块的特殊性质,进行一些测试
#变量,赋值,计算
[root@node-249 ~]# awk 'BEGIN{a=1;b=2;print a,b,a+b}'
1 2 3
#计算
[root@node-249 ~]# awk 'BEGIN{print 10/3}'
3.33333
#打印
[root@node-249 ~]# awk 'BEGIN{print "hello, world!"}'

2.5 pattern模块

关于匹配模式,在帮助文档中,我们可以看到

Patterns
       AWK patterns may be one of the following:

              BEGIN
              END
              BEGINFILE
              ENDFILE
              /regular expression/
              relational expression
              pattern && pattern
              pattern || pattern
              pattern ? pattern : pattern
              (pattern)
              ! pattern
              pattern1, pattern2

排除BEGINEND模式,大体可以分三种,即

  1. 正则表达式
    /reg/
  2. 判断表达式
    express,例如前文中提到的$3<100$5 != 10 || $3 ==3
  3. 范围表达式
    /pattern1/,/pattern2/
1. awk中的正则表达式

字符串匹配模式 (string-matching pattern) :测试一个字符串是否包含一段可以被正则表达式匹配

  • (1) /reg/ 匹配整个输入行有没有使用默认的字段,即使用$0
[root@node-249 ~]# awk -F: '/root/ {print $1,$3,$6}' /etc/passwd
root 0 /root
operator 11 /root
  • (2) ~/reg/ 匹配单个被分隔的项目是否被匹配,比如$1,$2
[root@node-249 ~]# awk -F: '$1 ~ /root/ {print $1,$3,$6}' /etc/passwd
root 0 /root
[root@node-249 ~]# awk -F: '$1~ /root/ {print $1,$3,$6}' /etc/passwd
root 0 /root
[root@node-249 ~]# awk -F: '$1 ~/root/ {print $1,$3,$6}' /etc/passwd
root 0 /root

~两侧有无空格均可

  • (3) !~/reg/ 不包含为true
[root@node-249 ~]# awk -F: '$1 !~/root/ {print $1,$3,$6}' /etc/passwd
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
...

awk支持regular符号表见下(元字符)

元字符含义例子
\转义字符awk -F "||" {print $1} worker.txt//打印每条记录的第1个字段
^匹配一行的开始,在[]中表示非awk '/^[^U]/ {print}' countries//匹配不以U为开头的记录
$匹配一行的结束awk '/a$/ {print}' countries//记录匹配以a为结尾
[ ][ ] 匹配一个范围如:[A-Za-z]或[^0-9]awk '$1~/[A-G]/ {print $0}' countries//第1个字段匹配存在A-G字母(范围)
|awk '$1~/A|B/ {print $0}' countries //第1个字段匹配存在A或B字母
( )匹配一个字符串awk '$1~/(USA)/ {print $0}' countries//第1个字段匹配为USA的记录
.匹配任意1个字符(有且仅有1个)awk '$4 ~/^A..a$/ {print}' countries //第4个字段匹配以A开头且结尾为a的4个字符的
+匹配1或多个字符awk '$1~/US+/ {print $0}' countries//第1个字段匹配存在US或USS等多个S
?匹配 0 或 1个字符awk '$1~/S?/ {print $0}' countries//第1个字段匹配存在0或1个S
*匹配0或多个字符awk '$1~/S*/ {print $0}' countries//第1个字段匹配存在0或多个个S

awk中正则的组合符号主要是直接组合(reg1)(regs)reg1|reg2
比如:(Asian|European|North American) (male|female) (black|blue)bird
一共匹配12种字符串,由Asian male blackbirdNorth American female bluebird

3**Mario||27||female||Japan为例,如果要分割该行

[root@node-249 ~]# cat awk1.txt|awk -F"\|\||\*\*" '{print $1}'
awk: warning: escape sequence `\|' treated as plain `|'
awk: warning: escape sequence `\*' treated as plain `*'
3
[root@node-249 ~]# cat awk1.txt|awk -F"|||**" '{print $1}'
3
[root@node-249 ~]# cat awk1.txt
3**Mario||27||female||Japan

[](范围-互补)中,内部的字符即使需要直接对元字符的匹配也不需要进行转义,

[root@node-249 ~]# cat awk1.txt
3**Mario||27||female||Japan
^123
[root@node-249 ~]# cat awk1.txt |awk "/^[^^]/"'{print $1}'

采用其余方式使用元字符进行字符串匹配的都需要对元字符进行转义
匹配以一个^或多个^^为首的字符串

[root@node-249 ~]# cat awk1.txt
3**Mario||27||female||Japan
^123
^^321
[root@node-249 ~]# cat awk1.txt |awk "/^(\^)+/"'{print $1}'
^123
^^321
2. awk中的判断表达式

该模式主要是 常规运算符如: <,>..,配合常规逻辑运算符 &&,||..等使用,使用方式类似于:

if(express){
    //do something
}
[root@node-249 ~]# ll | awk 'NR >1 {print}'
-rw-------.  1 root root      1260 Feb  2  2023 anaconda-ks.cfg
-rw-r--r--   1 root root      9027 May 28 10:59 a.txt
-rw-r--r--   1 root root       136 Jun 14 14:42 awk1.sh
-rw-r--r--   1 root root        39 Jun 17 18:17 awk1.txt
drwxr-xr-x   2 root root       140 Jul  5  2023 bin
[root@node-249 ~]# ll | awk '$5 >4096 {print}'
-rw-r--r--   1 root root      9027 May 28 10:59 a.txt
-rw-r--r--   1 root root   2025407 May  6 15:20 default.json
-rw-r--r--   1 root root   1693394 May  6 16:10 default.json.bak
-rw-r--r--   1 root root   8486976 Jul  3  2023 docker-compose-Linux-x86_64
-rw-r--r--   1 root root  32491520 May 28 11:02 jobs.tar
3. 范围表达式

范围模式由一个逗号分开的两个正则表达式组成,范围匹配如:/reg1/,/reg2/

[root@node-249 ~]# awk  'BEGIN{FS=":"} $1 ~/root/,/lp/ {print $1}' /etc/passwd
root
bin
daemon
adm
lp
[root@node-249 ~]# awk '/USSR/,/China/ {print}' test1
USSR 8649 275 Asia
Canada 3852 25 North America
China 3705 1032 Asia
[root@node-249 ~]# awk '/USSR/,/^[C]/ {print}' test1
USSR 8649 275 Asia
Canada 3852 25 North America
[root@node-249 ~]# cat test1
USSR 8649 275 Asia
Canada 3852 25 North America
China 3705 1032 Asia
USA 3615 237 North America
Brazil 3286 134 South America
India 1267 746 Asia
Mexico 762 78 North America
France 211 55 Europe
Japan 144 120 Asia

2.6 END模块

END在awk读取完所有的文件的时候,再执行END模块,一般用来输出一个结果(累加,数组结果),也可以是和BEGIN模块类似的结尾标识信息。与BEGIN格式一样,但是END模式仅在awk处理完所有输入行后才进行处理。

如果awk作为bash中处理文本的一个工具,那么笔者上面整理的基本满足需求了。但如果当做一个语言学习,那还远远不够。
awk还包括判断,循环,函数等等高级功能,笔者这里只是简单整理了日常可能用到的功能。如果想深入学习,不妨看看书
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值