[Tool] awk初学

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 ---
posted on 2025-06-22 22:46  风惊庭前叶  阅读(16)  评论(0)    收藏  举报