Linux三剑客之awk
Linux 三剑客之 awk
简介
awk
是 Linux 下的一个命令行工具,同时也是一种语言解析引擎。它具备完整的编程特性,可以用于文本处理、数据提取和报告生成等任务。
awk 的应用
- 数据筛选和格式化
- 文本文件处理和分析
- 报表生成
- 数据转换和清洗
优点
- 强大灵活:支行复杂的文本处理和数据分析。
- 高效:能够快速处理大文件和数据流。
- 内置编程语言:提供完整的编程特性,包括变量,控制结构和函数。
基本语法
awk 'pattern {action}' file
pattern
:匹配条件action
:在匹配条件成立时执行的操作
awk 上下文变量
开始和结束:BEGIN 和 END
awk 'BEGIN {print "开始处理"} END {print "处理结束"}' file
BEGIN
:在处理文件中的每一行之前执行的动作。END
:在处理文件中的所有行之后执行的动作。
输出示例
开始处理
处理结束
行数:NR(重点)
awk '{print NR, $0}' file
NR
:当前记录的行号。
输出
1 line1
2 line2
3 line3
字段与字段数:$1、$2、...、$NF、NF(重点)
awk '{print $1, $2, NF}' file
$1
:第一个字段。$2
:第二个字段。$NF
:最后一个字段。NF
:字段数。
假设file
文件内容如下
field1 field2 field3
fieldA fieldB
输出
field1 field2 3
fieldA fieldB 2
整行:$0
awk '{print $0}' file
$0
:当前记录的整行内容。
假设file
文件内容如下
hello world
awk is powerful
输出
hello world
awk is powerful
字段分隔符:FS(重点)
awk 'BEGIN {FS=","}{print $1, $2}' file
FS
:输入字段的分隔符。
假设 file
文件内容如下
name,age
Alice,30
Bob,25
输出
name age
Alice 30
Bob 25
输出数据的字段分隔符:OFS
awk 'BEGIN {FS=","; OFS=":"} {print $1, $2}' file
OFS
:输出数据的字段分隔符。
输出
name:age
Alice:30
Bob:25
记录分隔符:RS
awk 'BEGIN {RS=""; FS="\n"} {print $1, $2}' file
RS
:输入记录的分隔符。
假设file
文件内容如下
record1 line1
record1 line2
record2 line1
record2 line2
输出
record1 line1 record1 line2
record2 line1 record2 line2
输出字段的行分隔符:ORS
awk 'BEGIN {ORS=";"} {print $1, $2}' file
ORS
:输出字段的行分隔符。
假设file
文件内容如下
name age
Alice 30
Bob 25
输出
name age;Alice 30;Bob 25;
awk 字段变量用法
使用 -F 参数指定字段分隔符
语法
awk -F '分隔符' '{print $1, $2}' file
- 使用
-F
参数指定输入字段的分隔符。
案例
awk -F ':' '{print $1, $2}' file
假设file
文件内容如下
field1:field2
data1:data2
输出
field1 field2
data1 data2
使用 BEGIN{} 指定分隔符
语法
awk 'BEGIN {FS="分隔符"} {print $1, $2}' file
- 在
BEGIN
块中指定输入字段的分隔符。
案例
awk 'BEGIN {FS=","} {print $1, $2}' file
假设file
文件内容如下
name,age
Alice,30
Bob,25
输出
name age
Alice 30
Bob 25
$0 代表当前的记录
语法
awk '{print $0}' file
$0
:当前记录的整行内容。
案例
awk '{print $0}' file
假设 file
文件内容如下
hello world
awk is powerful
输出
hello world
awk is powerful
$1 代表第一个字段
语法
awk '{print $1}' file
$1
:第一个字段
案例:
awk '{print $1}' file
假设 file 文件内容如下:
hello world
awk is powerful
输出
hello
awk
$N 代表第 N 个字段
语法
awk '{print $N}' file
$N
:第 N 个字段
案例
awk '{print $2}' file
假设 file 文件内容如下:
hello world
awk is powerful
输出
world
is
$NF 代表最后一个字段
语法
awk '{print $NF}' file
$NF
:最后一个字段
案例
awk '{print $NF}' file
作用:
假设 file 文件内容如下:
hello world example
awk is powerful tool
输出
example
tool
$(NF-1) 代表倒数第二个字段
语法
awk '{print $(NF-1)}' file
$(NF-1)
:倒数第二个字段
案例
awk '{print $(NF-1)}' file
假设 file 文件内容如下:
hello world example
awk is
输出
world
awk
pattern 表达式
awk
中的pattern
用于选择和处理符合条件的文本行,模式可以是正则表达式或比较表达式。
正则匹配
整行匹配
-
匹配包含
Error
的行awk '/Error/'
/Error/
是正则表达式,用于匹配包含Error
的行。
字段匹配
-
匹配第 2 个字段中包含
xxx
的行awk '$2~/xxx/' 文件
$2~/xxx/
表示匹配第二个字段中包含 xxx 的行。
比较表达式
数值比较
匹配字段值大于某个数值的行
wsk '$2>2' 文件
$2>2
:表示匹配第二个字段的值大于 2 的行。
等值比较
匹配字段值等于某个值的行
awk '$1=="b"' 文件
$1=="b"
:表示匹配第一个字段的值等于 b 的行。
awk pattern 匹配表达式案例
开始块(BEGIN)
BEGIN
块在处理数据之前执行,通常用于初始化变量或设置输入输出格式
awk 'BEGIN {print "Start processing..."}'
BEGIN {print "Start processing..."}
在开始处理数据前打印一条消息。
结束块(END)
END
块在处理完所有数据后执行,通常用于输出结果
awk 'END {print "Processing complete."}'
END {print "Processing complete."}
在处理数据完成后打印一条消息。
行数表达式
-
仅输出第二行内容
awk 'NR==2' 文件
NR==2
匹配第二行。NR 是当前行号。
-
从第二行开始处理
awk 'NR>1' 文件
NR>1
跳过第一行,处理从第二行开始的所有行。
区间选择
-
从某模式到另一模式
选择从 aa 到 bb 之间的所有行: awk '/aa/,/bb/' 文件
/aa/,/bb/
从匹配aa
的行开始,到匹配bb
的行结束。
-
从某模式到特定行
选择从包含 1 的行到第二行之间的所有行: awk '/1/,NR==2' 文件
/1/
表示从匹配1
的行开始,NR==2
表示结束于第二行。
awk 动作行为表达式
awk
的动作用于对匹配的行执行操作,包括打印、赋值和其他数据处理。
打印
-
打印整行
打印每一行的内容: awk '{print $0}' 文件
$0
代表整行内容。
-
打印特定字段
只打印每一行的第二个字段: awk '{print $2}' 文件
$2
代表每行的第二个字段。
赋值
-
字段赋值
修改第一个字段的值并打印整行: awk '{$1="abc"; print $0}' 文件
{$1="abc"; print $0}
将第一个字段设置为 abc,然后打印整行。
处理函数
-
原始内容
awk '{print $0}' 文件
$0
表示整行内容。
-
更新后内容
更新字段后打印修改后的整行内容: awk '{$1=$1; print $0}' 文件
{$1=$1; print $0}
更新字段以重新计算字段值,并打印整行。
单行转多行
将单行数据按指定分隔符拆分为多行:
echo 1:2:3 | awk 'BEGIN {RS=":"} {print $0}'
输出
1
2
3
BEGIN {RS=":"}
设置记录分隔符为冒号 :,将输入按冒号拆分为多条记录。{print $0}
打印每一条记录。
多行变单行
将多行数据合并为一行,并且指定分隔符分隔
用换行符作为记录分隔符
echo '1
2
3' | awk 'BEGIN {RS=""; FS="\n"; OFS=":"} {$1=$1; print $0}'
输出
1:2:3
BEGIN {RS=""; FS="\n"; OFS=":"}
:设置记录分隔符为空字符串(整个输入作为一条记录),字段分隔符为换行符 '\n',输出字段分隔符为冒号:
。{$1=$1; print $0}
:重新计算字段,并打印修改后的整行。
用输出记录分隔符
echo '1
2
3' | awk 'BEGIN {ORS=":"} {$1=$1; print $0}'
输出
1:2:3:
BEGIN {ORS=":"}
设置输出记录分隔符为冒号:
。
计算平均数
计算每组数据的平均值
echo '1,10
2,20
3,30' | awk 'BEGIN {total=0; FS=","} {total+=$2} END {print total/NR}'
输出
20
BEGIN {total=0; FS=","}
初始化total
变量,并设置字段分隔符为逗号,
。{total+=$2}
累加第二个字段的值。END {print total/NR}
在处理完所有数据后,打印总和除以记录数的平均值。
awk 的词典结构数组
awk
的数组是稀疏矩阵,类似于 Python 中的字典,可以用于统计和处理数据。
-
统计各机构的总营业额
echo 'a, 1, 10 a, 2, 20 a, 3, 30 b, 1, 5 b, 2, 6 b, 3, 7' | awk '{data[$1]+=$3} END {for (k in data) print k, data[k]}'
输出
a 60 b 18
{data[$1]+=$3}
将每个机构的营业额累加到data
数组中。END {for (k in data) print k, data[k]}
在处理完所有数据后,遍历 data 数组并打印每个机构及其总营业额。
-
使用数组计算各机构的平均营业额
echo 'a, 1, 10 a, 2, 20 a, 3, 30 b, 1, 5 b, 2, 6 b, 3, 7' | awk '{data[$1]+=$3; count[$1]+=1;} END {for (k in data) print k, data[k]/count[k]}'
输出
a 20 b 6
{data[$1]+=$3; count[$1]+=1;}
累加营业额,并统计每个机构的记录数。END {for (k in data) print k, data[k]/count[k]}
在处理完所有数据后,计算每个机构的平均营业额并打印。
总结
- 简介
- awk 的应用
- 优点
- 用法