awk 的优缺点
优点:
- 强大的文本处理能力: 特别擅长处理结构化、列式数据。
- 内置变量丰富: 简化了字段、行号等信息的获取。
- 支持正则表达式: 灵活的模式匹配。
- 支持变量和数组: 可以进行更复杂的逻辑和数据统计。
- 可编写脚本: 适合处理复杂的任务。
- 执行效率高: 对于大数据文件处理通常比一些脚本语言更快。
缺点:
- 语法相对独特: 与其他常见的脚本语言(如 Python、Perl)有所不同,初学者可能需要适应。
- 不适合处理二进制文件: 主要用于处理纯文本文件。
- 复杂逻辑可读性下降: 过于复杂的 awk 脚本可能会变得难以理解和维护。
打印
内容:
Name,Age,City,Occupation
Alice,30,New York,Engineer
Bob,24,London,Designer
Charlie,35,Paris,Doctor
David,28,New York,Engineer
Eve,42,London,Artist
打印整行
awk '{print}' data.csv
输出完整内容。
打印指定字段
# -f: 指定间隔符号为逗号
awk -F',' '{print $1, $3}' data.csv
输出为:
Name City
Alice New York
Bob London
Charlie Paris
David New York
Eve London
比较大小
awk -F',' '$2 > 30 {print $0}' data.csv
输出:
Charlie,35,Paris,Doctor
Eve,42,London,Artist
比较字符
awk -F',' '$3 == "New York" {print $1, $2}' data.csv
输出:
Alice 30
David 28
正则表达式
awk -F',' '$4 ~ /Engineer/ {print $0}' data.csv
输出:
Alice,30,New York,Engineer
David,28,New York,Engineer
逻辑
awk -F',' '$3 != "London" {print $0}' data.csv
# 或者使用正则表达式不匹配
# ~:匹配正则表达式
# !: 表示逻辑非
# 打印城市不是London的行
awk -F',' '$3 !~ /London/ {print $0}' data.csv
输出:
Name,Age,City,Occupation
Alice,30,New York,Engineer
Charlie,35,Paris,Doctor
David,28,New York,Engineer
字段修改
修改字段
awk -F',' 'BEGIN{OFS=","} {if ($4 == "Engineer") $4="Software Developer"; print}' data.csv
输出:
Name,Age,City,Occupation
Alice,30,New York,Software Developer
Bob,24,London,Designer
Charlie,35,Paris,Doctor
David,28,New York,Software Developer
Eve,42,London,Artist
增加字段
为每行增加一个“Status”字段,并设置为“Active”。
awk -F',' 'BEGIN{OFS=","} {$5="Active"; print}' data.csv
输出结果:
Name,Age,City,Occupation,Active
Alice,30,New York,Engineer,Active
Bob,24,London,Designer,Active
Charlie,35,Paris,Doctor,Active
David,28,New York,Engineer,Active
Eve,42,London,Artist,Active
删除字段
awk无法直接删除字段,只能将内容置空
awk -F',' 'BEGIN{OFS=","} {$3=""; print}' data.csv
输出
Name,Age,,Occupation
Alice,30,,Engineer
Bob,24,,Designer
Charlie,35,,Doctor
David,28,,Engineer
Eve,42,,Artist
awk也可以通过重新输出的方式打印想要的字段
awk -F',' 'BEGIN{OFS=","} {print $1, $2, $4}' data.csv
输出:
Name,Age,Occupation
Alice,30,Engineer
Bob,24,Designer
Charlie,35,Doctor
David,28,Engineer
Eve,42,Artist
进阶:脚本和块
数据块
BEGIN 和 END 块在处理数据前和处理数据后执行。
计算平均年龄:
awk -F',' '
BEGIN {
sum_age = 0;
count = 0;
# 打印头部,跳过第一行
print "Average Age Report"
}
NR > 1 { # 跳过CSV文件的标题行 (NR == 1)
sum_age += $2;
count++;
}
END {
if (count > 0) {
print "Total individuals processed:", count;
print "Sum of ages:", sum_age;
print "Average age:", sum_age / count;
} else {
print "No data to process."
}
}' data.csv
- BEGIN 块初始化变量并打印报告头。
- NR > 1 确保我们从第二行(数据行)开始处理。
- sum_age += $2 将第二列(年龄)累加到sum_age 变量中。
- count++ 记录处理的人数。
- END 块计算并打印平均值。
输出:
Average Age Report
Total individuals processed: 5
Sum of ages: 159
Average age: 31.8
变量和数组
awk 支持自定义变量和关联数组。
统计每个城市的总人数:
awk -F',' '
BEGIN {
print "City Population Report"
}
NR > 1 {
city_counts[$3]++; # 使用城市名作为数组索引,每次出现就加1
}
END {
for (city in city_counts) { # 遍历数组
print city ": " city_counts[city]
}
}' data.csv
输出:
City Population Report
New York: 2
London: 2
Paris: 1
更加复杂的 awk 脚本
对于更复杂的 awk 程序,你可以将其写入一个独立的脚本文件(例如 my_script.awk),然后用 -f 选项执行:
# my_script.awk
BEGIN {
FS = ","; # 设置输入分隔符
OFS = ","; # 设置输出分隔符
print "Name,Age,New_Occupation,Status" # 打印新的头部
}
NR > 1 {
new_occupation = $4;
if ($4 == "Engineer") {
new_occupation = "Software Engineer";
} else if ($4 == "Designer") {
new_occupation = "UX/UI Designer";
}
# 打印原始姓名、年龄,以及新的职业和状态
print $1, $2, new_occupation, "Active";
}
END {
print "--- Processing complete ---"
}
执行:
awk -f my_script.awk data.csv
输出:
Name,Age,New_Occupation,Status
Alice,30,Software Engineer,Active
Bob,24,UX/UI Designer,Active
Charlie,35,Doctor,Active
David,28,Software Engineer,Active
Eve,42,Artist,Active
--- Processing complete ---