读取分隔文本文件时如何展平AAA/ABV/ABP嵌套记录结构?
需求:合并分隔文本文件中的关联记录
我有一个竖线分隔的文本文件,内容如下:
AAA|C0421002|D|20180102091621|CD|UKDC|PB|PORTAL|301873|OPER| ABV|E_ABERDARE|20161113|RF|16|20171229| ABP|1|F|.051|I| ABP|2|F|.047|I| ABP|3|F|.019|I| ABV|E_ASHWW-1|20161113|RF|16|20171229| ABP|1|F|0|E| ABP|2|F|0|E| ABP|3|F|0|E| ABV|E_ASLVW-1|20161113|RF|16|20171229| ABP|1|F|1.204|E| ABP|2|F|.974|E| ABP|3|F|1.025|E| AAA|C0421002|D|20180108092341|CD|UKDC|PB|PORTAL|302513|OPER| ABV|E_ABERDARE|20161117|RF|16|20180105| ABP|1|F|.051|I| ABP|2|F|.048|I| ABP|3|F|.041|I| ABV|E_ASHWW-1|20161117|RF|16|20180105| ABP|1|F|0|E| ABP|2|F|0|E| ABP|3|F|0|E| ABV|E_ASLVW-1|20161117|RF|16|20180105| ABP|1|F|5.487|E| ABP|2|F|5.485|E| ABP|3|F|5.484|E|
需要将每个ABV记录与其上方最近的AAA记录、下方对应的所有ABP记录合并为一行,目标格式如下:
AAA|C0421002|D|20180102091621|CD|UKDC|PB|PORTAL|301873|OPER|ABV|E_ABERDARE|20161113|RF|16|20171229|ABP|1|F|.051|I|ABP|2|F|.047|I|ABP|3|F|.019|I| AAA|C0421002|D|20180102091621|CD|UKDC|PB|PORTAL|301873|OPER|ABV|E_ASHWW-1|20161113|RF|16|20171229|ABP|1|F|0|E|ABP|2|F|0|E|ABP|3|F|0|E| AAA|C0421002|D|20180102091621|CD|UKDC|PB|PORTAL|301873|OPER|ABV|E_ASLVW-1|20161113|RF|16|20171229|ABP|1|F|1.204|E|ABP|2|F|.974|E|ABP|3|F|1.025|E| AAA|C0421002|D|20180108092341|CD|UKDC|PB|PORTAL|302513|OPER|ABV|E_ABERDARE|20161117|RF|16|20180105|ABP|1|F|.051|I|ABP|2|F|.048|I|ABP|3|F|.041|I| AAA|C0421002|D|20180108092341|CD|UKDC|PB|PORTAL|302513|OPER|ABV|E_ASHWW-1|20161117|RF|16|20180105|ABP|1|F|0|E|ABP|2|F|0|E|ABP|3|F|0|E| AAA|C0421002|D|20180108092341|CD|UKDC|PB|PORTAL|302513|OPER|ABV|E_ASLVW-1|20161117|RF|16|20180105|ABP|1|F|5.487|E|ABP|2|F|5.485|E|ABP|3|F|5.484|E|
尝试用for循环实现但未成功,求解决方法。
解决方案
方法1:Python实现
通过逐行读取文件,维护当前的AAA、ABV记录以及ABP记录列表,当遇到新的AAA或ABV时,将上一组关联记录合并输出。
current_aaa = "" current_abv = "" abp_lines = [] # 替换为你的输入文件路径和输出文件路径 with open("input.txt", "r") as f, open("output.txt", "w") as out_f: for line in f: line = line.strip() if not line: continue if line.startswith("AAA|"): # 输出上一组未处理的ABV+ABP if current_abv and abp_lines: merged = current_aaa + current_abv + "".join(abp_lines) out_f.write(merged + "\n") current_aaa = line current_abv = "" abp_lines = [] elif line.startswith("ABV|"): # 输出上一组未处理的ABV+ABP if current_abv and abp_lines: merged = current_aaa + current_abv + "".join(abp_lines) out_f.write(merged + "\n") current_abv = line abp_lines = [] elif line.startswith("ABP|"): abp_lines.append(line) # 处理最后一组记录 if current_abv and abp_lines: merged = current_aaa + current_abv + "".join(abp_lines) out_f.write(merged + "\n")
方法2:awk实现
利用awk的状态变量保存当前的AAA、ABV和ABP内容,逐行判断并合并输出。
BEGIN { FS = "" # 按字符读取,避免竖线分隔符干扰开头判断 } /^AAA\|/ { if (abv != "" && abp != "") { print aaa abv abp } aaa = $0 abv = "" abp = "" next } /^ABV\|/ { if (abv != "" && abp != "") { print aaa abv abp } abv = $0 abp = "" next } /^ABP\|/ { abp = abp $0 next } END { if (abv != "" && abp != "") { print aaa abv abp } }
使用方式:将上述代码保存为merge.awk,执行以下命令处理文件:
awk -f merge.awk input.txt > output.txt
内容的提问来源于stack exchange,提问作者Jason Grotto
相关产品推荐
相关产品推荐

