如何修改Linux命令以基于查找文件更新源文件并保留不匹配记录
解决根据查找文件更新源文件的问题
嘿,我看你现在的代码只能提取源文件里和查找文件不匹配的记录,却没法更新匹配项的内容。咱们来修改一下awk命令,让它同时搞定「更新匹配记录」和「保留不匹配记录」这俩事儿,还能正确保留表头~
核心思路
咱们的目标是:
- 先把查找文件(lkp file)里的
call_id(转成大写避免大小写问题)和对应的call_nm存成一个键值对 - 然后遍历源文件(src file):
- 第一行表头直接输出就行
- 数据行如果
call_id在查找文件的键值对里,就用查找文件的call_nm替换;要是不在,就原样保留原行
修改后的完整代码
我调整了你的代码结构,还补充了必要的逻辑:
import os def get_col_index(file, col): # 用with语句更安全,避免文件没关闭 with open(file, encoding="utf-8-sig") as f: header = f.readline().strip() header_list = header.split('\001') return str(header_list.index(col) + 1) # 这里替换成你实际的文件路径哦 lkp_file = "your_lkp_file.txt" src_file = "your_src_file.txt" trgt_file = "your_target_file.txt" # 获取需要的列索引:call_id在两个文件的位置,还有lkp里的call_nm位置 lkp_call_id_col = get_col_index(lkp_file, 'call_id') lkp_call_nm_col = get_col_index(lkp_file, 'call_nm') src_call_id_col = get_col_index(src_file, 'call_id') # 构建awk命令,用f-string拼接更清晰 matcher_string = f'''awk -F '\\001' ' # 处理第一个文件(lkp file) NR==FNR {{ if (NR > 1) {{ # 跳过表头 # 把call_id转大写当键,存储对应的call_nm id[toupper(${lkp_call_id_col})] = ${lkp_call_nm_col} }} next # 处理完lkp就跳到下一个文件 }} # 处理第二个文件(src file) NR==1 {{ # 输出表头 print $0 next }} {{ current_id = toupper(${src_call_id_col}) if (current_id in id) {{ # 匹配到了,输出原call_id + lkp的call_nm print ${src_call_id_col} "\\001" id[current_id] }} else {{ # 没匹配到,输出原行 print $0 }} }}' {lkp_file} {src_file} > {trgt_file} ''' os.system(matcher_string)
关键改动说明
- 新增列索引:之前只获取了
call_id的索引,现在加上了查找文件里call_nm的索引,这样才能拿到要更新的值 - awk逻辑补全:
- 专门处理表头,避免把表头当成数据行处理
- 对匹配的行,用查找文件的
call_nm替换源文件的对应值;不匹配的直接保留原行
- 输出方式调整:用
>而不是>>写入目标文件,这样每次运行都会生成新的结果,不会重复追加旧内容
测试结果
用你给的示例数据跑的话,输出完全符合你的预期:
100的QC会被更新成QZ105的XY因为和查找文件一致,保持不变110、115不在查找文件里,原样保留
内容的提问来源于stack exchange,提问作者Shivika
相关产品推荐
相关产品推荐

