Linux 三剑客之 awk 命令

今天来简单说下 linux 三剑客之一 awk, 概念这里不再赘述,直接看示例:

如果熟悉,只是来看下总结,可点击这里.

语法格式:

awk [options] 'script' var=value file(s)

测试文件

先创建两个测试文件:

class1.txt:

zhaoyun 85 87
guanyu 87 88
liubei 90 86

class2.txt:

caocao 92 87 90
guojia 99 96 92

1. 打印内容的第一列

打印文件的第一列,使用 awk 的 print 函数,$1 表示第一列

$ awk '{print $1}' class1.txt
zhaoyun 85

2. 打印多列

比如我们想打印文件的第一列和第三列,可以这样写:

$ awk '{print $1, $3}' class1.txt
zhaoyun 87
guanyu 88
liubei 86

3. 打印首列和末列

  • 首列可以使用 $1 表示
  • 末列可以使用 $NF 表示,NF 表示目前的记录被分割的字段的数目,NF 可以理解为 Number of Field
$ awk '{print $1,$NF}' class1.txt
zhaoyun 87
guanyu 88
liubei 86

4. 打印倒数第 N 列

如果我们想打印倒数第二列,可以这样写:

$ awk '{print $(NF-1)}' class1.txt
85
87
90

5. 打印行号

打印行号,使用 NR 变量,如:

$ awk '{print NR, $0}' class1.txt
1 zhaoyun 85 87
2 guanyu 87 88
3 liubei 90 86
  • NR Number of Records 表示行号,注意前面没有 $ 符号, 如果加了 $NR 表示第 NR 列。
  • $0 表示整行内容。

如果我们想要在行号后加个点呢,可以这样写:

$ awk '{print NR".", $0}' class1.txt
1. zhaoyun 85 87
2. guanyu 87 88
3. liubei 90 86

6. 指定分隔符

awk 默认是以空格分隔,如果是其他分隔符,可以使用 -F 参数指定,如以逗号分隔(先手动修改下之前的 class1.txt 为逗号分割):

awk -F, '{print $1}' class1.txt
awk -F , '{print $1}' class1.txt
awk -F ',' '{print $1}' class1.txt

上面三种写法都行, 还能用指定内置变量 FS 来指定分隔符,如:

awk -v FS=, '{print $1}' class1.txt

7. 分别指定输入和输出分隔符

前面我们指定的分隔符是输入分隔符,输出默认还是空格,如果我们想指定输出分隔符,可以指定内置变量 OFS,如:

awk -v FS=, -v OFS=- '{print $1, $2}' class1.txt

这样输入分隔符是 , 输出分隔符是 -

8. 多文件行号独立

对于多个文件,如果直接使用之前的 NR 变量,每个文件的行号是连续的,如:

$ awk '{print NR, $0}' class1.txt class2.txt
1 zhaoyun 85 87                                                        
2 guanyu 87 88                                                         
3 liubei 90 86                                                         
4 caocao 92 87 90                                                      
5 guojia 99 96 92

想要独立行号,可以使用 FNR 变量,如:

$ awk '{print FNR, $0}' class1.txt class2.txt
1 zhaoyun 85 87                                                                                                   
2 guanyu 87 88                                                                                                    
3 liubei 90 86                                                                                                    
1 caocao 92 87 90
2 guojia 99 96 92

9. 输出文件名

如果在上面那个的基础上,想要输出文件名,可以使用内置变量 FILENAME,如:

$ awk '{print FILENAME, FNR, $0}' class1.txt class2.txt
class1.txt 1 zhaoyun 85 87                                                                                                  
class1.txt 2 guanyu 87 88                                                                                                   
class1.txt 3 liubei 90 86                                                                                                   
class2.txt 1 caocao 92 87 90                                                                                                
class2.txt 2 guojia 99 96 92 

10. 前置后置操作

还是刚才那个例子,如果我们想在内容前后输出点内容,那么可以使用 BEGIN 和 END 操作符,如:

$ awk 'BEGIN{print "start"} {print FNR, $1, $2, $3} END{print "end"}' class1.txt class2.txt
start          
1 zhaoyun 85 87
2 guanyu 87 88 
3 liubei 90 86
1 caocao 92 87
2 guojia 99 96
end

比如用 NR 组合 End 就可以统计一个文件的行数:

$ awk 'END {print NR}' class1.txt
3

11. 文件级的前置后置操作

如果想要在每个文件开始读取和读取结束时执行一些操作,可以使用 BEGINFILE 和 ENDFILE 操作符,如用来统计每个文件的行数:

$ awk 'BEGINFILE{print "文件:", FILENAME} ENDFILE{print "行数:", FNR}' class1.txt class2.txt
文件: class1.txt
行数: 3
文件: class2.txt
行数: 2

BEGINFILE 和 ENDFILE 操作符是 gawk 特有的,其他版本可能不支持。

12. 接收外部变量

如果我们想要在 awk 脚本中接收外部变量,比如变量声明输出分隔符,可以使用 -v 参数,如:

$ var1="_"
$ awk -v OFS=$var1 '{print $1, $2, $3}' class1.txt
zhaoyun_85_87
guanyu_87_88
liubei_90_86

13. 判断条件

如果我们想要在 awk 中加入判断条件,可以使用 if 语句,如只输出第 2-3 行:

awk '{if (NR == 2 || NR == 3) print $0}' class1.txt

总结

参数

  • -F: 指定分隔符, 默认是空格, 也可以使用内置变量 FS 来指定分隔符, 如 -v FS=,

变量

  • $0: 表示整行内容
  • $1: 第一列
  • NR:Number of Records, 表示行号
  • $NR: 前面加上了 $ 符号,表示第 NR 行
  • NF: Number of Fields, 表示目前的记录被分割的字段的数目
  • $NF: 前面加上了 $ 符号,表示最后一列
  • FNR: File Number of Records, 表示当前文件的行号, 多文件时行号独立
  • FILENAME: 当前输入文件的名称
  • FS: Field Separator, 输入分隔符
  • OFS: Output Field Separator, 输出分隔符
© 版权声明
THE END
喜欢就支持一下吧
点赞14赞赏 分享
评论 抢沙发

    暂无评论内容