在一行中搜索单个表达式的多次出现

时间:2017-02-15 07:30:25

标签: python unix sed

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

  1. 十进制数
  2. 长字符串
  3. 在第二列中,我想提取每个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中解决这个问题的任何想法?

4 个答案:

答案 0 :(得分:2)

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

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)

这可能适合你(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 :(得分:1)

这是我认为符合您要求的小python程序。它使用FBtrfor 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

测试数据:

IMAP stack trace:

=> 'A5 SELECT "Sent Messages" (CONDSTORE)'
<= '* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen $Forwarded)'
<= '* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen $Forwarded \\*)]'
<= '* 5890 EXISTS'
<= '* 0 RECENT'
<= '* OK [UIDVALIDITY 1365356160]'
<= '* OK [UIDNEXT 6529]'
<= '* OK [HIGHESTMODSEQ 323053126527109]'
<= 'A5 OK [READ-WRITE] Completed'
=> 'IDLE IDLE'
<= '+ idling'
=> DONE
<= 'IDLE OK Completed'
=> 'A6 APPEND "Sent Messages" {30917+}'
=> ‘some Valid MIME’
<= 'A6 NO [TRYCREATE] Mailbox does not exist'
error { [Error: Mailbox does not exist] textCode: 'TRYCREATE', source: 'protocol' }
appendUID undefined
=> 'IDLE IDLE'
<= '+ idling'

提供输出:

 <form autocomplete="off" method="post" action="">
   <p>Title:
     <input type="text" />
   </p>
   <input type="button" onclick="addItem()" value="Add Item">
   <input type="button" onclick="removeItem()" value="Remove Last Item">
   <table>
     <th>Name</th>

     <tr>
       <td>
         <input type="text" id="input1" name="input1" />
       </td>
       <td>
         <input type="hidden" id="input2" name="input2" />
       </td>
     </tr>
   </table>
   <input id="submit" type="submit" name="submit" value="Submit">
 </form>
<script language="javascript">
function addItem() {
return false;
}

function removeItem() {
return false;
}
</script>

答案 3 :(得分:1)

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']