在pfam输出fi中将多行连接成单行

2024-10-16 17:18:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我有多行数据:

TRINITY_GG_428_c0_g1_i1_orf1 PF13499.1 EF_hand_5
TRINITY_GG_428_c0_g1_i1_orf1 PF00036.27 efhand
TRINITY_GG_428_c0_g1_i1_orf1 PF13405.1 EF_hand_4
TRINITY_GG_428_c0_g1_i1_orf1 PF13833.1 EF_hand_6
TRINITY_GG_428_c0_g1_i1_orf1 PF13202.1 EF_hand_3
TRINITY_GG_429_c0_g1_i1_orf1 PF00156.22 Pribosyltran
TRINITY_GG_431_c5_g1_i1_orf1 PF00475.13 IGPD
TRINITY_GG_461_c0_g1_i1_orf1 PF01208.12 URO-D
TRINITY_GG_461_c0_g1_i1_orf1 PF12876.2 Cellulase-like

我要做的是把它们转换成一行:

^{pr2}$

匹配线总是相邻的。在

如何在sed/awk/Perl/Python中解决这个问题?在


Tags: 数据handggc5g1efi1c0
3条回答

使用GNU sed:

$ sed -r ':a;N;s/^([^ ]*)( .*)\n\1(.*)$/\1\2 |\3/;ta;P;D' infile
TRINITY_GG_428_c0_g1_i1_orf1 PF13499.1 EF_hand_5 | PF00036.27 efhand | PF13405.1 EF_hand_4 | PF13833.1 EF_hand_6 | PF13202.1 EF_hand_3
TRINITY_GG_429_c0_g1_i1_orf1 PF00156.22 Pribosyltran
TRINITY_GG_431_c5_g1_i1_orf1 PF00475.13 IGPD
TRINITY_GG_461_c0_g1_i1_orf1 PF01208.12 URO-D | PF12876.2 Cellulase-like

主要的部分是替换:它检查两行是否以相同的字符串开头(直到第一个空格),如果是,则连接这些行,从第二行删除字符串并用管道替换新行。在

拆分:

^{pr2}$

要使用BSD sed执行此操作,我们必须围绕标签拆分命令,并使用-E标志而不是-r

sed -E -e ':a' -e 'N;s/^([^ ]*)( .*)\n\1(.*)$/\1\2 |\3/;ta' -e 'P;D' infile

为了更好地衡量,我们可以更仔细地观察一下这种替代:

s/            # Start substitution
    ^         # Anchor at start of pattern space
    ([^ ]*)   # Match and capture non-space characters (group #1)
    ( .*)     # Capture up to end of line (group #2)
    \n        # Match newline
    \1        # Start of second line: match first capture group
    (.*)      # Capture rest of second line (group #3)
    $         # Anchor at end of pattern space
/             # Delimiter for substitution
    \1\2 |\3  # Substitute: captures groups 1 and 2, space, pipe, capture group 3
/             # End of substitution

您可以使用python regex来执行类似的操作

import re

out_lines = []
with open('file.txt', 'r') as f:
    key = None
    key_lines = []
    for line in f:
        m = re.match(r'^(\S+)\s(.+)$', line)
        k, v = m.group(1), m.group(2)
        if k != key:
            if key:
                out_lines.append('{0} {1}'.format(key, ' | '.join(key_lines)))
            key = k
            key_lines = [v]
        else:
            key_lines.append(v)
    else:
        if key:
            out_lines.append('{0} {1}'.format(key, ' | '.join(key_lines)))

with open('out.txt', 'w') as f:
    f.write('\n'.join(out_lines))

只需在当前行的第一个字段与上一行相同的情况下建立所有行的连接记录,然后在第一个字段的值发生更改时打印它:

$ awk '
    $1==prev { rec = rec " | " $2 " " $3 }
    $1!=prev { if (NR>1) print rec; rec=$0 }
    { prev=$1 }
    END { print rec }
' file
TRINITY_GG_428_c0_g1_i1_orf1 PF13499.1 EF_hand_5 | PF00036.27 efhand | PF13405.1 EF_hand_4 | PF13833.1 EF_hand_6 | PF13202.1 EF_hand_3
TRINITY_GG_429_c0_g1_i1_orf1 PF00156.22 Pribosyltran
TRINITY_GG_431_c5_g1_i1_orf1 PF00475.13 IGPD
TRINITY_GG_461_c0_g1_i1_orf1 PF01208.12 URO-D | PF12876.2 Cellulase-like

或者,如果您的输入行键不是连续的,并且您不关心输出顺序与输入顺序相同,并且您的输入文件足够小,可以将其全部保存在内存中,那么您可以使用哈希方法,建议使用不同的答案:

^{pr2}$

相关问题 更多 >