如何用awk统计标记间行数并插入指定字段?
问题:给地震波数据的震源行添加对应接收设备行数量
我有一组包含地震波走时及对应信息(包括震源、波到达排列上每个检波器的时间)的数据,需格式化后用于层析成像计算,但我对awk不太熟悉。现在需要将每个震源对应的接收设备行(r行)数量插入到该震源信息行(s行)的第4列,且每个s行对应的r行数量不固定。
数据格式示例:
震源行:s 0.01 0 0 -1 0
接收设备行:
r 0.1 0 0 1.218 0.01 r 0.15 0 0 1.214 0.01 r 0.2 0 0 1.213 0.01
输入示例:
s 0.01 0 0 -1 0 r 0.1 0 0 1.218 0.01 r 0.15 0 0 1.214 0.01 r 0.2 0 0 1.213 0.01 s 1.01 0 0 -1 0 r 0.05 0 0 1.159 0.01 r 0.1 0 0 1.127 0.01 r 0.15 0 0 1.106 0.01 r 0.2 0 0 1.115 0.01 r 0.25 0 0 1.107 0.01
期望输出:
s 0.01 0 3 -1 0 r 0.1 0 0 1.218 0.01 r 0.15 0 0 1.214 0.01 r 0.2 0 0 1.213 0.01 s 1.01 0 5 -1 0 r 0.05 0 0 1.159 0.01 r 0.1 0 0 1.127 0.01 r 0.15 0 0 1.106 0.01 r 0.2 0 0 1.115 0.01 r 0.25 0 0 1.107 0.01
解决方案:使用awk脚本实现
核心思路是先缓存当前震源行,统计后续接收行数量,遇到下一个震源行或文件结束时,再输出修改后的震源行和缓存的接收行。
直接运行以下awk命令处理数据(将input.txt替换为你的数据文件名,output.txt为输出文件名):
awk ' /^s/ { if (prev_s != "") { print prev_s, count, rest for (i=0; i<count; i++) print r_lines[i] } prev_s = $1 " " $2 " " $3 rest = $5 " " $6 count = 0 next } /^r/ { r_lines[count++] = $0 next } END { print prev_s, count, rest for (i=0; i<count; i++) print r_lines[i] } ' input.txt > output.txt
脚本逻辑说明
- 处理震源行(
^s):- 若已有缓存的上一个震源行,先输出修改后的该行(把统计的接收行数量插入第4列),再输出所有缓存的接收行。
- 缓存当前震源行的前3列、第5-6列内容,重置接收行计数器。
- 处理接收行(
^r):- 将整行存入数组,同时递增计数器统计数量。
- 文件结束时(
END块):- 输出最后一个震源行和对应的接收行,避免遗漏。
效果验证
将输入示例保存为input.txt,运行命令后,output.txt内容将与期望输出完全一致。
内容的提问来源于stack exchange,提问作者Dustin
相关产品推荐
相关产品推荐

