Skip to content

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 的应用
  • 优点
  • 用法