今天来简单说下 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, 输出分隔符
暂无评论内容