【问题标题】:Extracting two substrings with specific starting characters from a long string and concatenating them从长字符串中提取两个具有特定起始字符的子字符串并将它们连接起来
【发布时间】:2016-08-15 00:08:53
【问题描述】:

我试图从一个包含比我需要的多得多的长字符串中提取两条信息。我有一个制表符分隔的 .txt 文件,其格式重复了 115,000 行:

TRINITY_DN89_c0_g1_i1   blastx  match_part  2   388 5.00e-73    +   1   Target=UniRef90_UPI0005D06956 2 388;hin=2;hsn=1;db=uniref;hs=1;hf=0;hsl=387;hil=618;ql=390;pi=88.37;qc=99.23;hc=20.87;d=PREDICTED  uncharacterized family 31 glucosidase KIAA1161-like;tax=Plutella xylostellaTRINITY_DN89_c0_g1_i1 blastx  match_part  2   388 1.00e-72    +   1   Target=UniRef90_A0A0N1IHR0 2 388;hin=3;hsn=1;db=uniref;hs=1;hf=0;hsl=387;hil=647;ql=390;pi=82.95;qc=99.23;hc=19.94;d=Uncharacterized family 31 glucosidase KIAA1161;tax=Papilio;go=GO:0004553,GO:0005975

我想要结束的是开始值,在这种情况下,“TRINITY_DN89_c0_g1_i1”附加到每行末尾“go=GO:”之后的每个值。

在这种情况下我希望的输出如下:

TRINITY_DN89_c0_g1_i1=0004553       
TRINITY_DN89_c0_g1_i1=0005975

但是,TRINITY_go=GO: 之后的字符对于每一行都是不同的,它们代表我与相关基因本体术语注释一起组装的转录组中转录本的唯一标识符。

使用 awk 或 sed 似乎可以实现这一点,但我不确定如何提取这些特定部分,尤其是因为某些字符在行之间有所不同。

非常感谢任何帮助!

作为更新,我已将数据转换为以下格式,这绝对比以前更接近,感谢@shellter 的帮助:

TRINITY_DN30_c0_g1_i1=0004553,GO:0005975
TRINITY_DN89_c0_g1_i1=0004553,GO:0005975
TRINITY_DN89_c0_g2_i1=0004553,GO:0005975
TRINITY_DN63_c0_g1_i1=0004190
TRINITY_DN105_c0_g1_i1=0003964
TRINITY_DN123_c0_g1_i1=0016021,GO:0005524,GO:0005215
TRINITY_DN163_c1_g1_i1=0016021,GO:0005524,GO:0005215
TRINITY_DN163_c1_g1_i1=0016021
TRINITY_DN292_c0_g1_i1=0003677,GO:0006338,GO:0006357
TRINITY_DN223_c0_g1_i1=0005858,GO:0016887,GO:0003777,GO:0003341                                
TRINITY_DN223_c0_g1_i1=0005509,GO:0051014,GO:0045010,GO:0051016
TRINITY_DN284_c0_g1_i1=0007010

现在,我的问题是我希望每个 GO 值有 1 行,每行都以其关联的成绩单 ID 开头。例如,我想将上面的第一行更改为:

TRINITY_DN30_c0_g1_i1=0004553
TRINITY_DN30_c0_g1_i1=0005975

并对具有多个 GO 值的每一行执行相同的操作。需要明确的是,行可能有一个或多个 GO 值,有些行有很多。这可能吗?

谢谢!

【问题讨论】:

    标签: string awk sed extract


    【解决方案1】:

    鉴于您的样本数据,这里是测试台版本

    sed 's/ .*go=GO:/=/;s/,.*$//' <<< "TRINITY_DN89_c0_g1_i1   blastx  match_part  2   388 5.00e-73    +   1   Target=UniRef90_UPI0005D06956 2 388;hin=2;hsn=1;db=uniref;hs=1;hf=0;hsl=387;hil=618;ql=390;pi=88.37;qc=99.23;hc=20.87;d=PREDICTED  uncharacterized family 31 glucosidase KIAA1161-like;tax=Plutella xylostellaTRINITY_DN89_c0_g1_i1 blastx  match_part  2   388 1.00e-72    +   1   Target=UniRef90_A0A0N1IHR0 2 388;hin=3;hsn=1;db=uniref;hs=1;hf=0;hsl=387;hil=647;ql=390;pi=82.95;qc=99.23;hc=19.94;d=Uncharacterized family 31 glucosidase KIAA1161;tax=Papilio;go=GO:0004553,GO:0005975"
    

    输出

    TRINITY_DN89_c0_g1_i1=0004553
    

    替换模式的工作方式类似于,“找到行中的第一个空格,然后一直匹配到go=GO:。将所有这些替换为='。与s/,.*$// 相同的想法。这会找到第一个逗号在剩余的文本中,并匹配到行尾.*$,并替换为//(无)。

    鉴于您的数据在文件中,您只需将文件名作为参数传递给sed,并使用 shell 重定向写入新文件,即

    sed 's/ .*go=GO:/=/;s/,.*$//' file > outFile
    

    这允许您保留原始文件的备份,因此如果您在输出中发现问题,您不必花时间重新生成原始文件(或从存档中复制它,或其他任何方式)。

    如果您要将其构建到脚本解决方案中,并且您希望在整个过程中使用相同的文件名(无论内部数据的版本如何),sed 的新版本具有-i(就地)选项,所以...

    sed -i 's.....' file
    

    将就地编辑您的文件。

    如果您在 Mac 或其他基于 Berkely 的 Unix/Linux 版本上使用它,那么您必须告诉 -i 选项不要担心备份文件,然后使用

    sed -i"" 's....' file
    

    IHTH

    【讨论】:

    • 非常感谢您的快速回复!
    • 您在将行直接输入命令提示符时的第一个建议效果很好,但我不可能对数据文件中的每一行重复。您对文件本身使用的第二个建议似乎没有以正确的方式输出,我在第一行得到以下输出:TRINITY_DN30_c0_g1_i1 blastx match_part 260 517 1.00e-23 + 1 Target=UniRef90_UPI0006EAEBFB=0004553 你有什么想法吗什么可以解决这个问题?
    • @ScottCinel:“第一个建议”:。是的,这就是小样本数据的问题。 “第二个建议”:嗯..它应该工作。但这假设您要捕获的数据的第一部分始终位于该行中的第一个空格字符之前,并且只有一个 go=GO:。如果没有看到您的数据的更多详细信息,我看不到解决此问题的简单方法。并且(对不起,但是)我不想参与两个小时的数据调试会议。我试图给你一个开始的地方。
    • 请随意发布一个新的 Q,其中包含 2-3 行 较小 示例数据,该示例数据仍然说明了可能性范围,但更易于使用。祝你好运。
    • 嗯。我想我错过了解决您问题的关键点。您想从每行数据中检索 两个 值对吗?使您的数据更小的另一个原因(用“abc”、“def”、“xyz”等更短的字符串替换将被忽略的长字符串)。您可以返回源并重建数据文件,以便将 1 行数据输出为 2 行吗?这可能会简化你的问题。用你最好的样本数据版本编辑你的 Q 并发表一个小评论,我稍后会再看一遍(或者其他人会选择这个)。祝你好运。
    猜你喜欢
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    相关资源
    最近更新 更多