使用Bash脚本结合Awk拆分动态TSV/CSV文件为三个独立文件
动态TSV文件拆分需求与解决方案
需求说明
我有一个制表符分隔的动态TSV文件FileA.csv,每小时会更新:
Debit Count和Score Count区块下会新增一行数据Receipt Count区块下不会新增行,仅更新现有行的数值
需要将FileA.csv拆分为三个独立文件:ABC.csv(对应Debit Count区块)、DEF.csv(对应Score Count区块)、GHI.csv(对应Receipt Count区块),且这三个文件每小时都要被完全替换为最新内容。
示例文件
第3小时的FileA.csv
Debit Count VALUE hour 1 5 hour 2 81 hour 3 15 Score Count hour 1 31 hour 2 66 hour 3 9 Receipt Count age logs 23 bus logs 21 pig logs 7 dog logs 40
第7小时的FileA.csv
Debit Count VALUE hour 1 5 hour 2 81 hour 3 15 hour 4 20 hour 5 52 hour 6 33 hour 7 35 Score Count hour 1 31 hour 2 66 hour 3 9 hour 4 112 hour 5 15 hour 6 38 hour 7 21 Receipt Count age logs 13 bus logs 28 pig logs 85 dog logs 55
拆分后目标文件示例(第3小时)
ABC.csv:
Debit Count VALUE hour 1 5 hour 2 81 hour 3 15
DEF.csv:
Score Count hour 1 31 hour 2 66 hour 3 9
GHI.csv:
Receipt Count age logs 23 bus logs 21 pig logs 7 dog logs 40
尝试过的代码(存在问题)
awk f="ABC.csv DEF.csv GHI.csv" ' BEGIN {split(f,files)} /^Debit/ /^Score/ /^Receipt/ {n++} {print>files[n]}' FileA.csv
问题分析
这段代码的核心问题:
- 匹配条件错误:
/^Debit/ /^Score/ /^Receipt/是逻辑与,永远无法匹配任何行,应该用逻辑或|| - 未清空目标文件:
print>files[n]在awk中是追加模式,会导致旧文件内容残留,无法实现完全替换 - 未正确管理文件句柄:没有关闭已写完的文件,可能导致资源泄漏或内容刷新不及时
正确解决方案
使用以下awk脚本,可实现自动切换输出文件、清空旧内容、适配动态更新的需求:
BEGIN { # 定义三个目标文件的映射 files[1] = "ABC.csv" files[2] = "DEF.csv" files[3] = "GHI.csv" current_file_idx = 0 } # 匹配三个区块的标题行,切换输出文件 /^Debit Count/ || /^Score Count/ || /^Receipt Count/ { current_file_idx++ # 关闭上一个文件,避免资源占用 if (current_file_idx > 1) { close(files[current_file_idx - 1]) } # 用>模式清空目标文件并写入标题行 print > files[current_file_idx] next } # 普通行追加到当前目标文件 { print >> files[current_file_idx] } END { # 关闭最后一个文件 close(files[current_file_idx]) }
脚本说明
- BEGIN块:初始化目标文件列表和当前文件索引
- 标题行匹配:每次遇到三个区块的标题时,切换到下一个目标文件,关闭上一个文件并清空新文件写入标题
- 普通行处理:将非标题行追加到当前对应的目标文件
- END块:关闭最后一个文件,确保内容全部写入
使用方式
每小时执行以下命令即可完成拆分与替换:
awk -f split_script.awk FileA.csv
(也可将脚本直接写在命令行中,或加入定时任务如cron自动每小时运行)
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

