awk 的设计使得他非常适合处理由行列组成的文本数据. awk 还是一种编程语言环境, 他提供了正则表达式的匹配, 流程控制, 运算符, 表达式, 变量, 以及函数等一系列的程序设计语言所具备的特性.
2.awk 命令的基本语法
awk 命令的基本语法:
awk 匹配模式 {执行的操作}
2.1 awk 的工作流程
awk 处理数据时, 他会反复执行一下 4 个步骤:
1. 自动的从数据文件中读取文本的行.
2. 自动更新 awk 的内置系统变量的值. 例如: 列数变量 NF, 行数变量 NR, 行变量 $0, 各个变量 $1,$2 等.
3. 依次执行程序中的所有的匹配模式及其操作.
4. 当执行完程序的所有匹配模式和操作后, 如果数据文件中仍有未读取的数据行, 则返回第一步重复执行 1~4 的操作.
2.2 awk 的执行方式
用户通过 3 种方式来执行 awk 程序, 分别是命令行, awk 脚本, 可执行文件.
命令行语法 awk 'awk 程序语句' 待处理的文件 . 例如: awk '{ print }' a.txt
awk 脚本语法 awk -f awk 脚本 待处理的文件 .awk 脚本里依次写上 awk 程序语句即可.
可执行脚本语法 awk 脚本 待处理的文件 . 但是一定要指定命令解释器 #! /bin/awk -f . 脚本内容依次写上 awk 的程序语句即可.
2.3 特殊字符
$0: 表示整个当前行
$1: 每行第一个字段
NF: 字段数量变量
NR: 每行的记录号, 多文件记录递增
FNR: 与 NR 类似, 不过多文件记录不递增, 每个文件都从 1 开始
FS:BEGIN 时定义分隔符, 默认是空格或制表符.
RS: 输入的记录分隔符, 默认是换行符. awk 每次读取一行进行处理, 通过指定行分隔符, 来决定 awk 一次读取多少行. 例如: 指定行分隔符为空行, awk 每次读取有空格的地方.
\t: 制表符
\n: 换行符
~ : 匹配, 与 == 相比不是精确比较
!~: 不匹配, 不精确比较
== : 等于, 必须全部相等, 精确比较
!= : 不等于, 精确比较
&&: 逻辑与
||: 逻辑或
+: 匹配时表示 1 个或 1 个以上
/[0-9][0-9]+/: 两个或两个以上数字
/[0-9][0-9]*/ : 一个或一个以上数字
OFS: 输出字段分隔符, 默认也是空格, 可以改为制表符等
ORS: 输出的记录分隔符, 默认为换行符, 即处理结果也是一行一行输出到屏幕
-F ':' : 指定分隔符
3.awk 的模式匹配
awk 的匹配模式主要包括关系表达式, 正则表达式, 混合模式, BEGIN 模式, END 模式等.
3.1 关系表达式
awk 提供了许多关系运算符, 例如大于 > , 小于 <, 等于 == 等, awk 可以以关系表达式作为匹配模式, 当文本行满足关系表达式时, 则会执行响应的操作.
实例:
显示第二段大于 80 的行.
- # awk '$2> 80 { print }' 1.txt
- q 90
- e 86
- r 84
- y 98
表示第二列的值大于 80, 执行花括号里面的 print 操作.
3.2 正则表达式
awk 支持正则表达式匹配, 和 sed 一样, 需要放在两条斜线 /xx/ 之间.
实例:
- # awk '/^(w|r)/ { print }' 1.txt
- w 75
- r 84
表示匹配 w 或 r 并 print 出来.
3.3 混合模式
awk 支持关系表达式和正则表达式, 同时支持使用逻辑运算符.
&&: 逻辑与
||: 逻辑或
!: 逻辑非
实例:
- # awk '/^w/ && $2> 70 { print }' 1.txt
- w 75
两条匹配模式都为真, 才会显示.
- # awk '/^w/ || /^r/ { print }' 1.txt
- w 75
- r 84
两条匹配模式哪条为真显示哪条. 都为真都显示.
3.4 区间模式
区间模式是显示两条匹配模式之间的文本行. 格式如下:
匹配模式 1, 匹配模式 2
实例:
匹配 root 开头的行和 UID 为 3 之间的行.-F 指定分隔符.
- # awk -F ":" '/^root/, $3==3 { print }' 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
3.5 BEGIN 模式
BEGIN 模式是一种内置的模式, 该模式里的内容生命周期只会被执行一次, 一般用在脚本里面. 语法如下:
- #! /bin/awk -f
- BEGIN {
执行的操作 1
执行的操作 2
...
}
{ 对待处理的文件执行的操作 }
写成一行就是:
awk 'BEGIN { 执行的操作 1; 执行的操作 2; } { 对待处理的文件执行的操作 }' 待处理的文件
实例:
只使用 BEGIN 模式显示内容.
- # awk 'BEGIN { print"aaa"; print"======="}'
- aaa
- =======
使用 BEGIN 模式同时文件进行操作.
- # awk 'BEGIN { print"aaa"; print"======="} { print }' 1.txt
- aaa
- =======
- q 90
- w 75
- e 86
3.6 END 模式
END 模式也生命周期只会执行一次. 一般会把善后的工作放在 END 模式对应模块里. 在执行 END 模块之前, 必须执行操作或者执行 BEGIN 模式, 语法如下:
#! /bin/awk -f
{ 对待处理的文件执行的操作 }
END {
执行的操作 1
执行的操作 2
...
}
写成一行就是:
awk '{ 对待处理的文件执行的操作 } END { 执行的操作 1; 执行的操作 2; }' 待处理的文件
实例:
执行 END 模式, 前面必须有操作, 不然不能执行.
- # awk '{ print } END { print"aaa"; print"======="}' 1.txt
- q 90
- w 75
- e 86
- aaa
- =======
执行 BEGIN 模式和 END 模式
- # awk 'BEGIN { print"aaa"; print"======="} END { print"======="; print"aaa"}' 1.txt
- aaa
- =======
- =======
- aaa
4. 变量
awk 的变量包括自定义的变量和系统内置变量.
4.1 自定义变量和引用
要放在 BEGIN 模式里面, 不然不会执行成功. 引用变量直接跟变量名即可.
- # awk 'BEGIN { x=3; print x }'
- 3
4.2 系统内置变量
变量 | 说明 |
$0 | 表示当前整个文件的内容 |
$n | n 是整数,表示字段,每行第 N 个字段 & nbsp; |
NF | 表示当前记录的字段数,字段总数 |
NR | 每行的记录号,多文件记录递增,总行数 |
FNR | 与 NR 类似,不过多文件记录不递增,每个文件都从 1 开始 & nbsp; |
OFS | 写在条件的前面,用来指定 print 显示的列之间的分隔符。例如:awk -F ":" '{OFS="#"} $1=="root" {print $1,$2,$3,$4}' test.txt |
FILENAME | 表示正在处理的数据文件的名称 |
FS | 字段分隔符,默认是空格或制表符 |
RS | 行分隔符,默认是换行符。awk 每次读取一行进行处理,通过指定行分隔符,来决定 awk 一次读取多少行。例如:指定行分隔符为空行,awk 每次读取有空格的地方。 |
4.3 内置变量行分隔符 FS 字段分隔符 RS
awk 对文本进行处理是一行一行选取的, 然后对文本行进行处理.
因为系统变量 FS 默认的分隔符是换行符 "\n", 如果更改换行符则会每次读取到换行符的位置.
一般把 FS 和 RS 放在 BEGIN 模块里面.
实例 1:
指定 A 为分割符, 所以在处理后的 A 都换行符, 而不出现了.
ccc 下面的空格是文件本身的换行符 \ n.
- # cat 1.txt
- aaaAbbbAccc
- # awk '{ print } { print"===="}' 1.txt // 正常显示
- aaaAbbbAccc
- ====
- # awk 'BEGIN { RS="A"} { print }{ print"===="}' 1.txt // 指定 RS 之后
- aaa
- ====
- bbb
- ====
- ccc
- ====
实例 2:
把 A 当做字段分割符, 显示第一段, 则第一个 A 前面的内容为第一个字段符.
# cat 1.txt
a a a A b b b A c c c
- # awk '{ print $1 }' 1.txt // 正常显示
- a
- # awk 'BEGIN { FS="A"} { print $1 }' 1.txt // 指定 FS 之后. 空格不再是分隔符了.
- a a a
实例 3:
匹配第三段大于 500 的行, print 第 137 段, 分隔符用 #.
- # awk -F ":" '$3>500 { print $1"#"$3"#"$7}' test.txt
- nfsnobody#4294967294#/sbin/nologin
- mysql#501#/sbin/nologin
- # awk -F ":" '{OFS="#"}$3>500 { print $1,$3,$7}' test.txt
- nfsnobody#4294967294#/sbin/nologin
- mysql#501#/sbin/nologin
4.4 记录 $0 , 字段 $n 的引用
在 awk 中, 用户可以使用系统变量引用记录和字段.
虽然 awk 每次读取的是一行, 但在程序中记录和字段的引用都是针对当前整个文件或数据流来说的. 也就是如果要显示第一段会显示整个文件的第一段.
实例 1:
变量 $0 的值就是当前的记录值, 可以说是当前文件或者数据流的内容.
- # awk '{ print $0 }' 1.txt
- wang 85 92 79 87
- li 89 90 73 82
- zhao 81 88 92 81
实例 2:
$1 $2 $3 分别代表第一列 第二列 第三列的数值. 可以使用变量把数值的值相加.
- # awk '{ print $1, $2+$3+$4+$5}' 1.txt
- wang 343
- li 334
- zhao 342
5. 运算符和表达式
5.1 算术运算符
运算符 | 说明 | 举例 |
+ | 加法 | 1+2,表示求 1 和 2 的和,得 3 |
- | 减法 | 2-1,表示求 2 和 1 的差,得 1 |
* | 乘法 | 2*5,表示求 2 和 5 的积,得 10 |
/ | 除法 | 6/2,表示求 6 和 2 的商,得 3 |
% | 求余 | 5/2,表示求 5 除以 2 的余,得 1 |
^ | 幂运算 | 2^3,表示求 2 的 3 次方,得 8 |
实例:
- # awk 'BEGIN { print 3^2 , 5%2 , 5/2 , 2*3 }'
- 9 1 2.5 6
5.2 赋值运算
运算符 | 说明 | 举例 |
= | 赋值 | x=5,表示给 x 赋值为 5 |
+= | 前后相加后,再赋值给变量 | x+=5,表示 x 的值加上 5,再赋值给 x,等价 x=x+5 |
-= | 前数值减后面数值,再赋值给变量 | x-=5,表示 x 的值减 5,再赋值给 x |
*= | 前后相乘后,再赋值给变量 | x*=5,表示 x 的值乘 5,再赋值给 x |
/= | 前数值除以后面数值,再赋值给变量 | x/=5,表示 x 的值除以 5,再赋值给 x |
%= | 前数值除以后面数值的余,赋值给变量 | x%=5,表示 x 的值除以 5 的余数,再赋值给 x |
^= | 前数值的后面数值的次方,赋值给变量 | x^=5,表示 x 的值的 5 次方,再赋值给 x |
实例:
- # awk 'BEGIN { print x=5 , x+=5 , x%=6 , x*=3 }'
- 5 10 4 12
5.3 条件运算符
即当表达式的值为真时, 返回数值 1, 否则返回数值 2. 语法如下:
变量 =(表达式?"数值 1":"数值 2")
print 变量
实例:
判断打印成绩单中的数值是否大于 85, 大于 90 的给 A, 否则给 B.
- # awk '{ a=($2>85?"A":"B"); print a }' 1.txt
- B
- A
- B
- # awk '{ a=($2>85?"A":"B"); print $1,a }' 1.txt
- wang B
- li A
- zhao B
5.4 逻辑运算符
awk 支持 3 种逻辑运算, 分别是逻辑与, 逻辑或和逻辑非.
运算符 | 说明 | 举例 |
&& | 逻辑与,两个表达式都为真时,运行结果才为真 | 1>2&&3>2 的值为假 |
|| | 逻辑或,有一个为真,运行结果为真。两个表达式都为假时,运行结果为假 | 1>2||3>2 的值为真 |
! | 逻辑非,当表达式为真是,运行结果为假。当表达式为假时,运行结果为真 | !(1>2) 的值为真 |
实例:
当所有字段的数值都大于 80 时, 才显示出来.
- # awk '$2> 80 && $3> 80 && $4> 80 && $5> 80 { print }' 1.txt
- zhao 81 88 92 81
5.5 关系运算
awk 支持关系运算一般有: 大于, 小于, 等于 等..
运算符 | 说明 | 举例 |
> | 大于 | 5>2 的值为真 |
>= | 大于等于 | 8>=8 的值为真 |
< | 小于 | 5<6 的值为真 |
<= | 小于等于 | 5<=7 的值为真 |
== | 等于 | 5==5 的值为真 |
!= | 不等于 | 1!=2 的值为真 |
~ | 匹配 | $1~/^T / 表示匹配第一个字段以字符 T 开头的记录 |
!~ | 不匹配 | $1!~/a / 表示匹配第一个字段不包含字符 a 的记录 |
匹配运算符~ 不匹配运算符!~ 是 awk 特有的关系运算符, 语法如下:
字符串 ~ 表达式
字符串 !~ 表达式
匹配运算符: 判断字符串中是否包含表达式的字符串.
不匹配运算符: 判断字符串中是否不包含表达式的字符串.
实例:
匹配第一个字符 l 开头的记录.
- # awk '$1~/^l/ { print }' 1.txt
- li 89 90 73 82
匹配前十行, 第一段包含是 root 或者 lp 的行
- # awk -F ":" 'NR<=10 && $1 ~ /root|lp/' test.txt
- root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
awk 命令
来源: http://www.bubuko.com/infodetail-2577392.html