Awk 脚本化与高级应用

Awk 不仅可以在命令行中执行,还可以编写成 独立脚本 并用于自动化任务。本章介绍如何 在 Shell 脚本中使用 Awk,以及 高级控制逻辑(如状态机)。


1. 在 Shell 脚本中运行 Awk

如果需要重复使用 Awk 程序,可以将其写入 Shell 脚本

示例 1:逐行打印文件中的每个单词

创建 words 脚本

#!/bin/bash
awk '{c=split($0, s); for(n=1; n<=c; ++n) print s[n] }' $1

赋予可执行权限

chmod +x words

执行

./words input.txt

示例输入

Hello World!
Awk is powerful.

输出

Hello
World!
Awk
is
powerful.

可以在 vi/vim 中调用

:%!words

这样可以将文本转换为逐个单词的列表


2. 双倍行距与去除双倍空行

示例 2:双倍行距

#!/bin/bash
awk '{print; if (NF != 0) print ""}' -

vi 中调用

:%!double

效果:原文件的每一行都被增加了一行空行。

示例 3:去除双倍空行

方案

awk 'BEGIN {skip = 0}
     skip == 0 {if (NF == 0) {skip = 1} else {print}; next}
     skip == 1 {print; skip = 0; next}' input.txt

逻辑

  1. 变量 skip 记录是否跳过空行
    • 遇到第一个空行时,skip = 1,跳过打印。
    • 遇到第二个空行时,skip = 0,打印出来。
  2. 保证单独的空行不会被删除

示例输入

Line 1

Line 2


Line 3

示例输出

Line 1

Line 2

Line 3

3. 查找重复单词

需求:找出文本中 连续重复的单词

方案

awk 'BEGIN { dups=0; w="xy-zzy" }
     { for( n=1; n<=NF; n++) 
         { if ( w == $n ) { print w, "::", $0 ; dups = 1 } ; w = $n }
     } 
     END { if (dups == 0) print "No duplicates found." }' input.txt

示例输入

And the result was also also that it failed.

示例输出

also :: And the result was also also that it failed.
  • w="xy-zzy" 初始化为不会出现在文本中的字符串
  • 扫描每个单词,如果和上一个单词相同,则输出。
  • dups=1 标记是否存在重复单词,最后如果 dups==0 则输出 No duplicates found.

4. 变量在多行处理中的应用

示例 4:匹配特定值,并打印下一行

awk 'BEGIN {flag = 0}
     $1 == 1000 {flag = 1; next}
     flag == 1 {print; flag = 0; next}' input.txt

逻辑

  • 如果行的第一列是 1000,则标记 flag = 1 并跳过当前行。
  • 下一行被打印,之后 flag = 0,防止多次匹配。

示例输入

999 DataA
1000 DataB
1111 DataC
2222 DataD

示例输出

1111 DataC

**示例 5:匹配 1000 并打印 后 5 行

awk 'BEGIN {counter = 0}
     $1 == 1000 {counter = 5; next}
     counter > 0 {print; counter--; next}' input.txt

逻辑

  1. 遇到 $1 == 1000 时,counter = 5
  2. 之后的 5 行都被打印counter--,直到 counter = 0

示例输入

500 DataX
1000 StartHere
2000 Data1
3000 Data2
4000 Data3
5000 Data4
6000 Data5
7000 Data6

示例输出

2000 Data1
3000 Data2
4000 Data3
5000 Data4
6000 Data5

5. Awk 状态机(State Machine)

如果需要在不同状态间切换,可以使用 状态机(State Machine) 记录当前状态。

示例 6:执行 5 个不同操作

awk 'BEGIN {state = 0}
     $1 == "START" {state = 1; next}
     state == 1 {print "Step 1:" $0; state = 2; next}
     state == 2 {print "Step 2:" $0; state = 3; next}
     state == 3 {print "Step 3:" $0; state = 4; next}
     state == 4 {print "Step 4:" $0; state = 5; next}
     state == 5 {print "Final Step:" $0; state = 0; next}' input.txt

示例输入

Hello World
START
Data A
Data B
Data C
Data D
Data E
More Data

示例输出

Step 1:Data A
Step 2:Data B
Step 3:Data C
Step 4:Data D
Final Step:Data E
  • state 变量控制执行步骤
  • 遇到 START 时,进入 state=1
  • 依次执行 state=1state=5
  • 执行 Final Step 后回到 state=0

总结

任务 Awk 代码
Shell 脚本调用 Awk awk '{print}' $1
双倍行距 awk '{print; if (NF != 0) print ""}'
去除多余空行 awk 'BEGIN {skip=0} skip==0 {if (NF==0) {skip=1} else {print}; next} skip==1 {print; skip=0; next}'
查找重复单词 awk 'BEGIN {dups=0; w="xy-zzy"} {for(n=1; n<=NF; n++) {if(w==$n){print w,"::",$0; dups=1} w=$n}} END {if(dups==0) print "No duplicates found."}'
匹配 1000 并打印下一行 awk 'BEGIN {flag=0} $1==1000 {flag=1; next} flag==1 {print; flag=0; next}'
匹配 1000 并打印后 5 行 awk 'BEGIN {counter=0} $1==1000 {counter=5; next} counter>0 {print; counter--; next}'
状态机示例 awk 'BEGIN {state=0} $1=="START" {state=1; next} state==1 {print "Step 1:", $0; state=2; next}'

🚀 下一章,我们将学习 Awk 的文件处理和数据分析!

Last modified: Thursday, 30 January 2025, 1:31 AM