批量提取ID对应信息异常:仅输出最后一条结果的问题求助
批量提取ID对应的tf_class和tf_family信息问题解决
问题背景
需要从id_info.txt中批量提取my_ids.txt里每个ID对应的tf_class和tf_family字段,但现有脚本仅输出最后一个ID的信息,调整循环结构后问题仍未解决。
用户现有脚本
初始脚本
for i in $(cat my_ids.txt); do for name in $i; do class=$(grep -A 25 $name id_info.txt | grep -E "tf_class"); family=$(grep -A 25 $name id_info.txt | grep -E "tf_family"); echo -e "$name\n\class\n\family"; done done
尝试的while循环脚本
while IFS= read -r line; do class=$(grep -A 25 $line id_infoc.txt | grep -E "tf_class"); family=$(grep -A 25 $line id_info.txt | grep -E "tf_family"); echo -e "$line\n\class\n\family"; done < my_ids.txt
输入文件示例
my_ids.txt
MA0052.4 MA0602.1 MA0497.1 MA0786.1 MA0515.1
id_info.txt(核心片段)
AC MA0052.4 XX ... CC tf_family:Regulators of differentiation CC tf_class:MADS box factors ... AC MA0602.1 XX ... CC tf_family:ARID-related CC tf_class:ARID ... AC MA0497.1 XX ... CC tf_family:Regulators of differentiation CC tf_class:MADS box factors ... AC MA0786.1 XX ... CC tf_family:POU domain factors CC tf_class:Homeo domain factors ... AC MA0515.1 XX ... CC tf_family:SOX-related factors CC tf_class:High-mobility group (HMG) domain factors ...
当前输出
MA0052.4 MA0602.1 MA0497.1 MA0786.1 MA0515.1 CC tf_class:High-mobility group (HMG) domain factors CC tf_family:SOX-related factors
期望输出
MA0602.1 CC ARID CC ARID-related MA0497.1 CC MADS box factors CC Regulators of differentiation MA0786.1 CC Homeo domain factors CC POU domain factors MA0515.1 CC tf_class:High-mobility group (HMG) domain factors CC tf_family:SOX-related factors
问题原因与解决方案
问题根源
- 变量引用错误:脚本中
echo -e "$name\n\class\n\family"里的\class和\family多了反斜杠,导致输出字符串而非变量值,且换行符使用错误。 - 文件名拼写错误:第二段脚本中
id_infoc.txt应为id_info.txt,导致无法匹配内容。 - 匹配范围失控:
grep -A 25可能会匹配到后续ID块的内容,干扰结果。
修正后的脚本
方案一:修复基础错误的bash脚本
while IFS= read -r name; do # 限定仅在当前ID对应的块内搜索,避免匹配后续内容 class=$(grep -A 50 "AC $name" id_info.txt | grep -m1 "tf_class") family=$(grep -A 50 "AC $name" id_info.txt | grep -m1 "tf_family") # 格式化输出,用制表符分隔字段 echo -e "$name\t$class\t$family" done < my_ids.txt
方案二:高效的awk处理脚本
适合大文件场景,无需多次调用grep:
# 先加载目标ID列表到数组 BEGIN { while ((getline id < "my_ids.txt") > 0) { target_ids[id] = 1 } } # 识别当前处理的ID /^AC / { current_id = $2 class = "" family = "" } # 捕获tf_class字段 /^CC tf_class:/ { if (target_ids[current_id]) { class = $0 } } # 捕获tf_family字段 /^CC tf_family:/ { if (target_ids[current_id]) { family = $0 } } # 遇到块结束符时输出结果 /^XX$/ { if (target_ids[current_id] && class != "" && family != "") { printf "%s\t%s\t%s\n", current_id, class, family } }
运行方式:awk -f extract_info.awk id_info.txt
说明
- 方案一修复了变量引用和文件名拼写问题,用
grep -m1确保只取当前块内的第一条匹配结果。 - 方案二通过awk一次性遍历文件,先加载目标ID,再逐块处理,效率更高,避免重复IO操作。
内容的提问来源于stack exchange,提问作者Katherine Chau
相关产品推荐
相关产品推荐

