AWK多行记录识别异常:基于第4列去重失效求助
解决AWK识别多行记录并基于第4列去重的问题
你已经找对了方向,但核心问题出在记录分隔符的识别上——你提到跨行记录以^M$(也就是\r\n)结尾,完整记录才以$(\n)结尾,直接把RS设为\n会把一条完整的多行记录拆成好几段,自然无法正确处理。
我给你写一个针对性的AWK脚本,它会先把跨行的片段拼接成完整记录,再按第4列去重:
BEGIN { FS = "\035" # 设置字段分隔符为\035 ORS = "\n" # 输出记录用换行分隔 } # 处理记录内的跨行片段:行尾带^M(\r)的都是记录的一部分 /\r$/ { sub(/\r\n?$/, "", $0) # 去掉行尾的\r和换行符 buf = buf $0 # 把当前行内容追加到缓冲区 next # 跳过后续处理,继续读下一行 } # 处理完整记录的最后一行:行尾没有^M,说明记录结束 { buf = buf $0 # 把缓冲区内容和当前行拼接成完整记录 if (!seen[$4]++) { # 检查第4列是否已经出现过 print buf # 第一次出现就打印完整记录 } buf = "" # 清空缓冲区,准备处理下一条记录 }
脚本工作原理:
- 累积跨行记录:遇到行尾带
\r的行,就把它的内容去掉换行符后加到缓冲区里,直到读到行尾不带\r的行——这时候缓冲区+当前行就是一条完整的记录。 - 按第4列去重:用
seen数组记录第4列的值是否已经出现过,只保留第一次出现的完整记录。
如果你的需求只是输出第4列的唯一值,而不是完整记录,可以稍微修改脚本:
BEGIN { FS = "\035" } /\r$/ { sub(/\r\n?$/, "", $0) buf = buf $0 next } { buf = buf $0 split(buf, fields, FS) # 把完整记录拆成字段数组 if (!seen[fields[4]]++) { print fields[4] # 只打印唯一的第4列值 } buf = "" }
这个脚本完美适配你的输入格式,不管记录有多长、有多少跨行片段,都能正确识别并去重。
内容的提问来源于stack exchange,提问作者Ali E
相关产品推荐
相关产品推荐

