2011-10-10 97 views
0

好清晨,提取字符串與正則表達式是不穩定的

我有我們在以前的職位上建立以下python正則表達式文件。這意味着提取任何類似'chr'+ number +':'+ bignumber「..」+ bignumber的信息(因此看起來像chr1:100000..120000) 如果將chr1切換爲chrX,正則表達式腳本不會「T工作了......

這裏是原始腳本:

# Opens each file to read/modify 
    infile='myfile.txt' 
    outfile='outfile.txt' 

    #import Regex 
    import re 

    with open (infile, mode='r', buffering=-1) as in_f, open (outfile, mode='w', buffering=-1) as out_f: 
     f = (i for i in in_f if '\t' in i.rstrip()) 
     for line in f: 
      _, k = line.split('\t',1) 
      x = re.findall(r'^1..100\t([+-])chr(\d+):(\d+)\.\.(\d+).+$',k) 
      if not x: 
       continue 
      out_f.write(' '.join(x[0]) + '\n') 

如果我改變了這一行:

x = re.findall(r'^1..100\t([+-])chrX(\d+):(\d+)\.\.(\d+).+$',k) 

我不能具體提取任何看起來像chrX等... 你也應該知道有些行可能是空的!

請幫助:)謝謝

+0

你說的那條線是完全一樣的 –

+0

你對「123100 +」前綴沒有任何說法。這可能是問題嗎?請顯示k的內容(使用'print repr(k)'),這個和那個不匹配。 –

回答

3

我不完全明白你的問題,但我會嘗試給出了基於代碼一些建議。

這裏最重要的一行:

x = re.findall(r'^1..100\t([+-])chr(\d+):(\d+)\.\.(\d+).+$',k) 

觀察:

0)我甚至不知道什麼buffering=-1將在呼叫做open()。我建議你擺脫這一點,並允許標準行爲,這是行緩衝。在這種情況下,您希望一次處理一行文件。 (默認值與指定buffering=1相同。)

1)re.findall()返回匹配列表。但是,通過在您的模式中使用$,您可以保證最多隻能獲得一次匹配,因爲每行只能有一行結束。所以你應該使用re.search()。您甚至可以使用re.match(),因爲您將^錨定到該行的開頭。

2)我不建議您使用.split()方法函數來擺脫領先選項卡。只需將標籤摺疊到正則表達式中即可。它更簡單快捷。

3)你的模式要求每行開始,像這樣的字符串:

1aa100 
100100 
1xx100 
1xy100 

這是你想要的嗎?每行是否始終以「100」結尾的數字開頭?如果它始終是一個數字,您可能需要在模式中使用\d而不是.

4)您需要上面匹配的數字之後的選項卡。然後你有一個匹配組,匹配一個'+'或' - ',並讓你收集匹配的值。我很好奇你會用它做什麼。

5)圖案chr\d+將匹配chr0chr1chr11chr111等的數字的任何組合,具有1位的最小長度。我不確定你是否期望它實際上匹配大寫'X'(你談到匹配chrX),但它肯定不會。

6)你匹配一個數字,兩個實際時期和另一個數字。這看起來完全正確,對我很好。然後,第二個數字後,您一起使用.+。這需要在行結束之前有一個或多個額外的字符。我想知道這是否會導致您的問題。也許你應該使用.*匹配零個或多個額外的字符?

7)如果您使用re.match()而不是re.findall(),則不需要使用x[0]即可進入匹配組。

8)如果您有一個匹配組m,' '.join(m)不起作用。你得到一個類型錯誤。您需要改用' '.join(m.groups())。 9)我認爲與chr..分開的兩個數字本身相當不錯,所以也許你可以放鬆模式的其餘部分,只是匹配那些。

10)我總是喜歡預編譯我的正則表達式模式。速度更快,然後您可以在編譯的模式上使用方法函數。例如,如果pat是預編譯的正則表達式,則可以使用pat.search(line)來搜索一行文本。

把我的建議,這裏是一些Python代碼,你可以試試:

import re 

infile='myfile.txt' 
outfile='outfile.txt' 

pat = re.compile(r'([+-])chr([^:]+):(\d+)\.\.(\d+)') 

with open(infile, mode='r') as in_f, open(outfile, mode='w') as out_f: 
    for line in in_f: 
     if '\t' not in line.rstrip(): 
      continue 
     m = pat.search(line) 
     if not m: 
      continue 
     out_f.write(' '.join(m.groups()) + '\n') 

編輯:既然你似乎想認字符串chrX爲有效,我改變了上面的示例代碼。而不是\d來匹配一個數字,它現在使用[^:]來匹配除冒號以外的任何內容。上面的代碼應該匹配chr1:chrX:,或者其他任何東西。

+0

哇感謝了很多。現在我發現在我的原始文章中插入了錯字。如果我有chr [number]:[int}] .. [int]可以工作,但是當我需要提取chr [letter]:[int] .. [int]時根本不起作用。它似乎不識別字母,而只識別數字。這是我的觀點。非常感謝我明天會嘗試你的建議並更新這篇文章。謝謝! – madkitty

+0

作品像一個魅力^^ – madkitty

+0

嘿,我需要適應這個代碼來適應我們的數據。我再次遇到問題..我應該發佈一個新的問題或介意從這裏簽入? – madkitty