如何用awk/sed将CSV文件中匹配规则的断行追加到上一行
CSV断行拼接解决方案
之前命令失效的原因
- 正则写法错误:POSIX标准中
[:space:]这类字符类必须放在方括号分组内才能生效,直接写"[:space:]*只会匹配引号和:/s/p/a/c/e几个字符的任意组合,无法匹配空白字符。 - 字段统计逻辑错误:awk默认按空白分割字段,直接用
NF<24统计的是空白分隔的段落数,不是逗号分隔的CSV字段数,结果完全不符合预期。 - 缺少多行缓存逻辑:仅逐行判断打印,没有把断行暂存后和后续行拼接的逻辑,无法实现断行合并。
可行实现方案
采用awk流式处理,不需要把整个文件加载进内存(256G内存完全冗余,哪怕几十G的CSV也能流畅跑),核心逻辑:
- 用缓冲区逐行累积读入的内容
- 实时统计缓冲区中逗号的总数量
- 当缓冲区同时满足「逗号总数>=24」、「行尾匹配固定格式`",Y,H"(Y、H为单个单词,允许前后存在任意空白)」两个条件时,判定为完整行,输出后清空缓冲区
- 最后处理文件末尾可能残留的未输出内容
基础版命令(完全匹配规则)
awk ' { # 当前行追加到缓冲区 buf = buf $0 # 统计缓冲区中逗号总数量 comma_cnt = gsub(/,/, ",", buf) # 判定是否为完整行 if (comma_cnt >= 24 && buf ~ /"[[:space:]]*,[[:space:]]*[[:alnum:]_]+[[:space:]]*,[[:space:]]*[[:alnum:]_]+[[:space:]]*$/) { print buf buf = "" } } END { # 输出最后残留的内容 if (buf != "") print buf } ' check.csv > fixed_check.csv
大文件优化版
针对超大体积CSV优化,避免每次全量扫描缓冲区统计逗号数,运行速度更快,同时兼容Y、H包含横杠、点等非字母数字的单词场景:
awk -F, ' { buf = buf $0 total_comma += (NF - 1) # 兼容任意非逗号、非空白的单词格式 if (total_comma >= 24 && buf ~ /"[[:space:]]*,[[:space:]]*[^,[:space:]]+[[:space:]]*,[[:space:]]*[^,[:space:]]+[[:space:]]*$/) { print buf buf = "" total_comma = 0 } } END { if (buf != "") print buf } ' check.csv > fixed_check.csv
示例验证
针对给出的拆分样例,命令会自动逐行累积:
- 第一组拆分:先读入
a, b, c,存入缓冲区,逗号数不足24不输出;再读入"()", h, k追加到缓冲区,当X部分字段凑够24个逗号、且结尾匹配固定格式时,自动输出拼接后的完整行。 - 第二组拆分:依次读入
a, b, c, d, "()"、, h、, k逐行追加,直到满足完整行判定条件后一次性输出。
如果文件中Y、H允许包含空格(比如带空格的词组),只需要把正则里的
[^,[:space:]]+替换成对应匹配规则即可。
内容的提问来源于stack exchange,提问作者Crimson_91
相关产品推荐
相关产品推荐

