【问题标题】:Search for multiple occurrences of a single expression in a line在一行中搜索多次出现的单个表达式
【发布时间】:2017-07-03 17:52:25
【问题描述】:

我有一个包含两列的数据集:

  1. 十进制数
  2. 一长串

我想从第二列中提取每个 FBtr 编号(例如 FBtr0072798)并忽略其余部分。

 0.850359 EFF=INTRON(MODIFIER|||||drpr|||FBtr0072798|4|1),INTRON(MODIFIER|||||drpr|||FBtr0072799|4|1),INTRON(MODIFIER|||||drpr|||FBtr0309845|4|1),SYNONYMOUS_CODING(LOW|SILENT|atT/atA|I690||CG18171|||FBtr0072800|1|1)
 0.473555 EFF=INTRON(MODIFIER|||||drpr|||FBtr0072798|4|1),INTRON(MODIFIER|||||drpr|||FBtr0072799|4|1),INTRON(MODIFIER|||||drpr|||FBtr0309845|4|1),SYNONYMOUS_CODING(LOW|SILENT|agC/agT|S371||CG18171|||FBtr0072800|1|1),UPSTREAM(MODIFIER|||||CG12035|||FBtr0072766||1)
 0.969735 EFF=INTRON(MODIFIER|||||drpr|||FBtr0072798|4|1),INTRON(MODIFIER|||||drpr|||FBtr0072799|4|1),INTRON(MODIFIER|||||drpr|||FBtr0309845|4|1),SYNONYMOUS_CODING(LOW|SILENT|gtT/gtC|V366||CG18171|||FBtr0072800|1|1),UPSTREAM(MODIFIER|||||CG12035|||FBtr0072766||1)

我最终希望将其转换为长格式,以便每一行都包含来自第一列的十进制数字,并与单个 FBtr 数字配对。例如,

 0.850359   FBtr0072798
 0.850359   FBtr0072799
 0.850359   FBtr0309845
 0.850359   FBtr0072800
 0.473555   FBtr0072798
 0.473555   FBtr0072799
 0.473555   FBtr0309845
 0.473555   FBtr0072800
 0.473555   FBtr0072766
 0.969735   FBtr0072798
 0.969735   FBtr0072799
 0.969735   FBtr0309845
 0.969735   FBtr0072800
 0.969735   FBtr0072766

我一直在尝试逐步执行此操作,首先将 FBtr 编号提取到单独的列中:

 0.850359   FBtr0072798 FBtr0072799 FBtr0309845 FBtr0072800
 0.473555   FBtr0072798 FBtr0072799 FBtr0309845 FBtr0072800 FBtr0072766
 0.969735   FBtr0072798 FBtr0072799 FBtr0309845 FBtr0072800 FBtr0072766

然后从宽格式转换为长格式。

现在我在提取 FBtr 编号时遇到问题。我在 python 方面比 unix 更新手,所以我一直在尝试使用 unix,因为我对这种语言更熟悉一点。到目前为止,我尝试过的最有希望的事情是使用 sed 重复地对每个术语进行查找/替换搜索。

 sed -e 's/\(.* \).*\(FBtr[0-9]*\).*\(FBtr[0-9]*\).*\(FBtr[0-9]*\).*\(FBtr[0-9]*\).*\(FBtr[0-9]*\).*/ \1 \2 \3 \4 \5 \6/ g' file.txt

这不仅在所有重复中都很难看,而且只有在行中出现相同数量的 FBtr 时才有效,不幸的是没有。关于如何在 unix 或 python 中解决这个问题的任何想法?

【问题讨论】:

  • 如果你可以使用GNU Awk,请参考下面我的回答。

标签: python unix sed


【解决方案1】:

这可能对你有用(GNU sed):

sed -r '/\n/!s/FB[^|]*/\n&\n/g;s/^\s*(\S+)[^\n]*\n([^\n]*\n)/\1 \2\1 /;/FB/P;D' file

使用换行符隔离FB 字符串。然后使用匹配和反向引用,构造第一条记录并初始化第二条记录,只打印包含FB 字符串的行并重复直到所有当前行被完全处理。

【讨论】:

    【解决方案2】:

    如果您可以使用GNU Awk,它的gensub() 功能可以很酷,让您的生活更简单

    awk -F[[:space:],] '{for(i=1;i<=NF;i++) if (match($i,/FBtr([[:digit:]]+)/)) \
         {value=gensub(/^.*FBtr([[:digit:]]+).*$/,"FBtr\\1","g",$i); print $2,value} }' file
    0.850359 FBtr0072798
    0.850359 FBtr0072799
    0.850359 FBtr0309845
    0.850359 FBtr0072800
    0.473555 FBtr0072798
    0.473555 FBtr0072799
    0.473555 FBtr0309845
    0.473555 FBtr0072800
    0.473555 FBtr0072766
    0.969735 FBtr0072798
    0.969735 FBtr0072799
    0.969735 FBtr0309845
    0.969735 FBtr0072800
    0.969735 FBtr0072766
    

    【讨论】:

    • 我不确定它是否简单,但它似乎可以通过一次调整 - 打印 1 美元而不是 2 美元。谢谢!
    【解决方案3】:
    import re
    line = '0.850359 EFF=INTRON(MODIFIER|||||drpr|||FBtr0072798|4|1),INTRON(MODIFIER|||||drpr|||FBtr0072799|4|1),INTRON(MODIFIER|||||drpr|||FBtr0309845|4|1),SYNONYMOUS_CODING(LOW|SILENT|atT/atA|I690||CG18171|||FBtr0072800|1|1)'
    print(re.findall('FBtr(\d+)', line))
    

    ['0072798', '0072799', '0309845', '0072800']

    【讨论】:

    • 嗨,您能否详细说明您提出的答案?就目前而言,很难理解它为什么会起作用。
    • re.findall() 只是在字符串中找到所有出现的正则表达式并将它们作为列表返回
    • 如果将正则表达式更改为'(FBtr)(\d+)',结果将是[('FBtr', '0072798'), ('FBtr', '0072799'), ('FBtr', '0309845'), ('FBtr', '0072800')]
    • 请在回答中。
    【解决方案4】:

    这是我认为符合您要求的小 Python 程序。它使用str.split()str.startswith() 来查找所有以FBtr 开头的字符串。

    代码:

    for line in test_data:
        num, string = line.split(' ', 1)
        for field in string.split('|'):
            if field.startswith('FBtr'):
                print(num, field)
    

    测试数据:

    test_data = [x.strip() for x in """
        0.850359 EFF=INTRON(MODIFIER|||||drpr|||FBtr0072798|4|1),INTRON(MODIFIER|||||drpr|||FBtr0072799|4|1),INTRON(MODIFIER|||||drpr|||FBtr0309845|4|1),SYNONYMOUS_CODING(LOW|SILENT|atT/atA|I690||CG18171|||FBtr0072800|1|1)
        0.473555 EFF=INTRON(MODIFIER|||||drpr|||FBtr0072798|4|1),INTRON(MODIFIER|||||drpr|||FBtr0072799|4|1),INTRON(MODIFIER|||||drpr|||FBtr0309845|4|1),SYNONYMOUS_CODING(LOW|SILENT|agC/agT|S371||CG18171|||FBtr0072800|1|1),UPSTREAM(MODIFIER|||||CG12035|||FBtr0072766||1)
        0.969735 EFF=INTRON(MODIFIER|||||drpr|||FBtr0072798|4|1),INTRON(MODIFIER|||||drpr|||FBtr0072799|4|1),INTRON(MODIFIER|||||drpr|||FBtr0309845|4|1),SYNONYMOUS_CODING(LOW|SILENT|gtT/gtC|V366||CG18171|||FBtr0072800|1|1),UPSTREAM(MODIFIER|||||CG12035|||FBtr0072766||1)
    """.split('\n')[1:-1]]
    

    给出输出:

    0.850359 FBtr0072798
    0.850359 FBtr0072799
    0.850359 FBtr0309845
    0.850359 FBtr0072800
    0.473555 FBtr0072798
    0.473555 FBtr0072799
    0.473555 FBtr0309845
    0.473555 FBtr0072800
    0.473555 FBtr0072766
    0.969735 FBtr0072798
    0.969735 FBtr0072799
    0.969735 FBtr0309845
    0.969735 FBtr0072800
    0.969735 FBtr0072766
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-28
      • 2015-11-18
      • 1970-01-01
      • 2013-02-13
      • 2018-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多