AWK按指定列对比行并拆分列输出目标行的需求实现
解决已排序文件中指定列匹配后的逗号拆分问题
需求说明
处理已排序的文本文件,规则如下:
- 对比相邻行的第3列(
$3),若内容匹配 - 对第5列,以及第10至100列,按逗号
,拆分内容:- 若列内容无逗号,两行均输出原内容
- 若有逗号,第一匹配行输出逗号前的内容,第二匹配行输出逗号后的内容
输入输出示例
输入
chr6 113 1 A C ...... chr6 123 2 C G,T .... chr6 123 2 C G,T .....
输出
chr6 113 1 A C ...... chr6 123 2 C G .... chr6 123 2 C T .....
现有代码问题分析
你提供的awk代码片段存在以下问题:
- 未针对第5列、第10-100列做逗号拆分处理
- 未关联行与行之间第3列的匹配判断逻辑
- 代码缺少闭合语句,无法正常运行
改进后的解决方案
以下是实现需求的完整awk脚本:
BEGIN { OFS = " " } # 根据实际输入分隔符调整,比如制表符用"\t" # 存储上一行的关键信息 prev_key = "" prev_line = "" # 处理一对匹配行的函数 function process_pair(line1, line2) { # 拆分两行的字段 n1 = split(line1, f1, OFS) n2 = split(line2, f2, OFS) # 处理第5列的逗号拆分 split(f1[5], col5, ",") f1[5] = col5[1] f2[5] = (length(col5) > 1) ? col5[2] : col5[1] # 处理第10到100列的逗号拆分 for (i = 10; i <= 100 && i <= n1 && i <= n2; i++) { split(f1[i], coli, ",") f1[i] = coli[1] f2[i] = (length(coli) > 1) ? coli[2] : coli[1] } # 输出处理后的第一行 for (i = 1; i <= n1; i++) { printf "%s%s", f1[i], (i == n1 ? "\n" : OFS) } # 输出处理后的第二行 for (i = 1; i <= n2; i++) { printf "%s%s", f2[i], (i == n2 ? "\n" : OFS) } } # 逐行处理输入 { current_key = $3 if (current_key == prev_key) { # 当前行与上一行第3列匹配,处理这一对 process_pair(prev_line, $0) # 重置缓存,避免重复处理 prev_key = "" prev_line = "" } else { # 上一行无匹配,直接输出 if (prev_key != "") { print prev_line } # 缓存当前行信息 prev_key = current_key prev_line = $0 } } # 处理最后一行(无匹配的情况) END { if (prev_key != "") { print prev_line } }
脚本说明
- 分隔符设置:BEGIN块中
OFS需与输入文件的字段分隔符保持一致,默认用空格,可根据实际调整 - 行缓存逻辑:用
prev_key存储上一行第3列的值,prev_line存储上一行完整内容 - 匹配行处理:当相邻行第3列匹配时,调用
process_pair函数拆分指定列的逗号内容,分别赋值给两行后输出 - 边界处理:END块处理文件末尾无匹配的单行,确保所有行都被输出
内容的提问来源于stack exchange,提问作者Vonton
相关产品推荐
相关产品推荐

