基本语法

awk 的基本语法格式为 awk '{[pattern] action}' {filenames},注意只能使用单引号。

1
2
# 每行按空格或 TAB 分割,输出文本中的第 1、4 列
awk '{print $1,$4}' log.txt

常用选项

-F 指定分隔符

-F 选项用于指定字段分隔符,相当于内置变量 FS

1
2
# 使用逗号分割
awk -F, '{print $1,$2}' log.txt

-v 设置变量

1
awk -va=1 '{print $1,$1+a}' log.txt

-f 使用脚本文件

1
awk -f cal.awk log.txt

常用技巧

取倒数第 N 列

使用 $(NF-(n-1)) 可以取倒数第 N 列。其中 $NF 表示倒数第 1 列,$(NF-1) 表示倒数第 2 列。

1
2
# 取第 2 列、倒数第 1、倒数第 2、倒数第 4 列(以冒号为分隔符)
awk -F":" '{print $2,$(NF),$(NF-1),$(NF-3)}' /etc/passwd

将相同第一列的其他列进行拼接

1
sort b.txt | uniq | awk '{a[$1]=(a[$1]" "$2);} END{for(i in a) print i ":"a[i]}'

获取文本的某一行、某一列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 打印文件的第一列
awk '{print $1}' filename

# 打印文件的前两列
awk '{print $1,$2}' filename

# 打印完第一列,然后打印第二列(中间无空格)
awk '{print $1 $2}' filename

# 打印文本文件的总行数
awk 'END{print NR}' filename

# 打印文本第一行
awk 'NR==1{print}' filename

# 打印文本第二行第一列
sed -n "2,1p" filename | awk '{print $1}'

按行号筛选

1
2
3
4
5
# NR==n 表示打印第 n 行
awk 'NR==5{print}' filename

# NR!=n 表示不打印第 n 行
awk 'NR!=1{print}' filename

内置变量

变量说明
NF字段个数(当前行有多少列)
NR记录数(行号),从 1 开始,新的文件延续上面的计数
FNR读取文件的记录数(行号),从 1 开始,新的文件重新从 1 开始计数
FS输入字段分隔符,默认是空格
OFS输出字段分隔符,默认也是空格
RS输入行分隔符,默认为换行符
ORS输出行分隔符,默认为换行符

高级应用

对某一列进行去重

1
2
# 对 test.txt 文件的第三列进行去重
awk '{a[$3]=$0}END{for(i in a)print a[i]}' test.txt

列转行

1
2
3
4
5
# 将 a1.txt 文件中的列转为行,并用逗号隔开
awk '{printf "%s,",$1}' a1.txt

# 列转行后,去掉最后一个逗号
awk '{printf "%s,",$1}' a1.txt | sed 's/.$//'

跳过特定行

1
2
3
4
5
6
7
8
# 跳过文件里面的空行
awk '{if(!NF){next}}1' filename

# 跳过最后一行
awk 'NR > 1 { print prev } { prev = $0 }' file.txt

# 跳过第一行
awk 'NR!=1 { print }' file.txt

将列作为参数传递

使用 xargs -n 指定参数数量:

1
xxxxxx | awk '{if (NR>1) print $1" "$3}' | xargs -n2 sh -c 'echo $0 $1'

或者保存为变量再使用:

1
2
3
4
out=$(xxxxxx | awk '{if (NR>1) print $1" "$3}')
arg1=$(echo $out | cut -d' ' -f1)
arg2=$(echo $out | cut -d' ' -f2)
echo $arg1 $arg2