如何用sed保留制表符分隔文件中的GO:#######字符串及指定空行
解决制表符分隔文件中保留GO格式字符串的sed问题
问题背景
有一个大型制表符分隔文件,需要保留每行中任意数量的GO:#######格式字符串,以及仅包含英文句点的行。使用原有sed命令时,因正则贪婪匹配导致误删中间有效内容,无法得到期望结果。
原有命令
sed -r 's/ `.+` //g' file1.txt > file2.txt
现有内容
GO:1234567 `text1`moretext` GO:5373845 `diff`text` GO:5438534 `text`text . GO:3333333 `txt`text` GO:5553535 `misc`text . .
期望结果
GO:1234567 GO:5373845 GO:5438534 . GO:3333333 GO:5553535 . .
实际错误结果
GO:1234567 GO:5438534 `text`text . GO:3333333 GO:5553535 `misc`text . .
问题原因
原有命令中的.+是贪婪匹配,会从第一个开始匹配到距离最远的下一个,跳过中间的GO字段;同时仅匹配前后带制表符的...内容,导致行尾无制表符的非GO内容无法被清理。
解决方案
方法1:使用sed精准匹配清理非GO内容
通过正则精准定位并删除所有非GO格式的字段,同时保留句点行:
sed -E ' /^\.$/!{ s/([^ ]*GO:[0-9]{7}[^ ]*)/\1\n/g; s/[^\n]*\n//g; s/\n/ /g; s/^ | $//g } ' file1.txt > file2.txt
命令解释:
/^\.$/!:仅对非句点行执行操作s/([^ ]*GO:[0-9]{7}[^ ]*)/\1\n/g:将每个GO格式字段和其前后的制表符替换为“GO字段+换行符”,把GO字段单独拆分到每行s/[^\n]*\n//g:删除所有不包含换行符的内容(即非GO字段),只留下GO字段的行s/\n/ /g:将换行符替换为制表符,把GO字段重新用制表符分隔s/^ | $//g:删除行首和行尾多余的制表符
方法2:用awk更高效处理字段(推荐)
awk天生擅长处理分隔符字段,逻辑更清晰,适合大型文件:
awk -F' ' ' /^\.$/ {print; next} { line = "" for (i=1; i<=NF; i++) { if ($i ~ /^GO:[0-9]{7}$/) { line = line (line ? " " : "") $i } } print line } ' file1.txt > file2.txt
命令解释:
-F' ':指定制表符为字段分隔符/^\.$/ {print; next}:如果是仅含句点的行,直接打印并跳过后续处理- 遍历每行的所有字段,仅保留匹配
GO:#######格式的字段 - 将保留的字段用制表符连接后打印
内容的提问来源于stack exchange,提问作者timtimbruno
相关产品推荐
相关产品推荐

