पाठ के बहुस्तरीय ब्लॉक से मेल खाते हुए नियमित अभिव्यक्ति


105

मैं कई लाइनों तक फैला है कि पाठ के खिलाफ मिलान जब काम करने के लिए पायथन regex होने में थोड़ी परेशानी हो रही है। उदाहरण पाठ है ('\ n' एक नई पंक्ति)

some Varying TEXT\n
\n
DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF\n
[more of the above, ending with a newline]\n
[yep, there is a variable number of lines here]\n
\n
(repeat the above a few hundred times).

मैं दो चीजों को कैप्चर करना चाहता हूं: 'some_Varying_TEXT' भाग, और अपरकेस टेक्स्ट की सभी लाइनें जो एक कैप्चर में इसके नीचे दो लाइनें आती हैं (मैं बाद में न्यूलाइन वर्णों को हटा सकता हूं)। मैंने कुछ तरीकों के साथ कोशिश की है:

re.compile(r"^>(\w+)$$([.$]+)^$", re.MULTILINE) # try to capture both parts
re.compile(r"(^[^>][\w\s]+)$", re.MULTILINE|re.DOTALL) # just textlines

और बिना किसी भाग्य के बहुत से बदलाव। अंतिम एक-एक करके पाठ की पंक्तियों से मेल खाता है, जो कि मैं वास्तव में नहीं चाहता। मैं पहले भाग को पकड़ सकता हूं, कोई समस्या नहीं, लेकिन मैं अपरकेस टेक्स्ट की 4-5 पंक्तियों को पकड़ नहीं सकता। मैं माचिस करना चाहता हूं। समूह (1) कुछ_वेरिंग_Text और समूह (2) को लाइन 1 + लाइन 2 + लाइन 3 + आदि होना चाहिए, जब तक कि खाली लाइन का सामना न हो जाए।

अगर किसी को जिज्ञासु है, तो यह एक प्रोटीन बनाने वाले अमीनोक्साइड का एक क्रम है।


क्या पहली पंक्ति और अपरकेस टेक्स्ट के अलावा फ़ाइल में कुछ और है? मुझे यकीन नहीं है कि आप सभी पाठों को न्यूलाइन वर्णों में विभाजित करने और "some_Varying_TEXT" के रूप में पहला तत्व लेने के बजाय एक regex का उपयोग क्यों करेंगे।
अंकलजीव

2
हां, रेगेक्स इसके लिए गलत उपकरण हैं।

आपके नमूना पाठ में अग्रणी >चरित्र नहीं है । इसे होना चाहिए?
मिनीक्वायार्क

जवाबों:


114

इसे इस्तेमाल करे:

re.compile(r"^(.+)\n((?:\n.+)+)", re.MULTILINE)

मुझे लगता है कि आपकी सबसे बड़ी समस्या यह है कि आप ^और $एंकरों को लाइनफीड से मिलान करने की उम्मीद कर रहे हैं , लेकिन वे नहीं करते हैं। बहु मोड में, ^स्थिति तुरंत मेल खाता है निम्नलिखित एक नई पंक्ति और $स्थिति तुरंत मेल खाता पूर्ववर्ती एक नई पंक्ति।

ज्ञात हो, भी, कि एक नई लाइन में एक लाइनफीड (\ n), एक कैरिज-रिटर्न (\ r), या एक कैरिज-रिटर्न + लाइनफीड (\ r \ n) शामिल हो सकता है। यदि आप निश्चित नहीं हैं कि आपका लक्ष्य पाठ केवल लाइनफीड का उपयोग करता है, तो आपको regex के इस अधिक समावेशी संस्करण का उपयोग करना चाहिए:

re.compile(r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", re.MULTILINE)

BTW, आप यहाँ DOTALL संशोधक का उपयोग नहीं करना चाहते हैं; आप इस तथ्य पर भरोसा कर रहे हैं कि डॉट नईलाइन्स को छोड़कर सब कुछ से मेल खाता है।


यदि आप यह नियमित अभिव्यक्ति नहीं चाहते हैं कि आप किसी दूसरी टेक्स्ट फ़ाइल को खाली दूसरी पंक्ति के साथ मिलाएं। ;-)
मिनीक्वार्क

मेरी धारणा है कि लक्ष्य फाइलें खाली बनाम गैर-खाली लाइनों के एक निश्चित (और दोहराए जाने वाले) पैटर्न के अनुरूप होंगी, इसलिए इसे [AZ] निर्दिष्ट करना आवश्यक नहीं होना चाहिए, लेकिन यह संभवतः, या तो चोट नहीं पहुंचाएगा।
एलन मूर

इस समाधान ने खूबसूरती से काम किया। एक तरफ के रूप में, मैं माफी मांगता हूं, क्योंकि मैंने स्पष्ट रूप से स्थिति को पर्याप्त रूप से स्पष्ट नहीं किया है (और इस उत्तर की विलंबता के लिए भी)। आपकी सहायताके लिए धन्यवाद!
Jan

21

यह काम करेगा:

>>> import re
>>> rx_sequence=re.compile(r"^(.+?)\n\n((?:[A-Z]+\n)+)",re.MULTILINE)
>>> rx_blanks=re.compile(r"\W+") # to remove blanks and newlines
>>> text="""Some varying text1
...
... AAABBBBBBCCCCCCDDDDDDD
... EEEEEEEFFFFFFFFGGGGGGG
... HHHHHHIIIIIJJJJJJJKKKK
...
... Some varying text 2
...
... LLLLLMMMMMMNNNNNNNOOOO
... PPPPPPPQQQQQQRRRRRRSSS
... TTTTTUUUUUVVVVVVWWWWWW
... """
>>> for match in rx_sequence.finditer(text):
...   title, sequence = match.groups()
...   title = title.strip()
...   sequence = rx_blanks.sub("",sequence)
...   print "Title:",title
...   print "Sequence:",sequence
...   print
...
Title: Some varying text1
Sequence: AAABBBBBBCCCCCCDDDDDDDEEEEEEEFFFFFFFFGGGGGGGHHHHHHIIIIIJJJJJJJKKKK

Title: Some varying text 2
Sequence: LLLLLMMMMMMNNNNNNNOOOOPPPPPPPQQQQQQRRRRRRSSSTTTTTUUUUUVVVVVVWWWWWW

इस नियमित अभिव्यक्ति के बारे में कुछ स्पष्टीकरण उपयोगी हो सकते हैं: ^(.+?)\n\n((?:[A-Z]+\n)+)

  • पहले चरित्र ( ^) का अर्थ है "एक पंक्ति की शुरुआत में शुरुआत"। विदित हो कि यह स्वयं नईलाइन से मेल नहीं खाता है ($ के लिए समान है: इसका अर्थ है "एक नई पंक्ति से ठीक पहले", लेकिन यह स्वयं नई रेखा से मेल नहीं खाता है)।
  • तब का (.+?)\n\nअर्थ है "दो पात्रों के रूप में संभव के रूप में मैच (सभी पात्रों को अनुमति दी जाती है) जब तक आप दो newlines तक नहीं पहुंचते"। परिणाम (बिना नए अंक के) पहले समूह में रखा गया है।
  • [A-Z]+\nका अर्थ है "जब तक आप एक नई पंक्ति तक नहीं पहुंचते हैं, तब तक कई ऊपरी मामलों के पत्रों का मिलान करें। यह परिभाषित करता है कि मैं एक टेक्स्टलाइन क्या कहूंगा ।"
  • ((?:टेक्स्टलाइन का)+) मतलब एक या अधिक टेक्स्टलाइन से मेल खाता है, लेकिन प्रत्येक लाइन को एक समूह में नहीं रखा जाता है। इसके बजाय, डाल सभी textlines एक समूह में।
  • \nयदि आप अंत में एक डबल न्यूलाइन लागू करना चाहते हैं तो आप नियमित अभिव्यक्ति में एक फाइनल जोड़ सकते हैं ।
  • इसके अलावा, आप यकीन है कि के बारे में न्यू लाइन आप किस प्रकार का हो जाएगा (नहीं कर रहे हैं, तो \nया \rया \r\n) फिर बस के हर घटना की जगह नियमित अभिव्यक्ति को ठीक \nसे (?:\n|\r\n?)

1
मैच () केवल एक मैच देता है, लक्ष्य पाठ की शुरुआत में, लेकिन ओपी ने कहा कि प्रति फ़ाइल सैकड़ों मैच होंगे। मुझे लगता है कि आप इसके बजाय खोजकर्ता () चाहते हैं।
एलन मूर

6

यदि प्रत्येक फ़ाइल में केवल अमीनोसिड का एक क्रम है, तो मैं नियमित अभिव्यक्ति का उपयोग नहीं करूँगा। बस कुछ इस तरह:

def read_amino_acid_sequence(path):
    with open(path) as sequence_file:
        title = sequence_file.readline() # read 1st line
        aminoacid_sequence = sequence_file.read() # read the rest

    # some cleanup, if necessary
    title = title.strip() # remove trailing white spaces and newline
    aminoacid_sequence = aminoacid_sequence.replace(" ","").replace("\n","")
    return title, aminoacid_sequence

निश्चित रूप से सबसे आसान तरीका अगर केवल एक ही था, और इसके साथ काम करने योग्य भी है, अगर कुछ और तर्क जोड़े जाते हैं। इस विशिष्ट डेटासेट में लगभग 885 प्रोटीन हैं, और मुझे लगा कि एक रेगेक्स को इसे संभालने में सक्षम होना चाहिए।
Jan

4

लगता है:

^>([^\n\r]+)[\n\r]([A-Z\n\r]+)

\ 1 = some_varying_text

सभी कैप्स की \ 2 = लाइनें

संपादित करें (प्रमाण है कि यह काम करता है):

text = """> some_Varying_TEXT

DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF
GATACAACATAGGATACA
GGGGGAAAAAAAATTTTTTTTT
CCCCAAAA

> some_Varying_TEXT2

DJASDFHKJFHKSDHF
HHASGDFTERYTERE
GAGAGAGAGAG
PPPPPAAAAAAAAAAAAAAAP
"""

import re

regex = re.compile(r'^>([^\n\r]+)[\n\r]([A-Z\n\r]+)', re.MULTILINE)
matches = [m.groups() for m in regex.finditer(text)]

for m in matches:
    print 'Name: %s\nSequence:%s' % (m[0], m[1])

दुर्भाग्य से, यह नियमित अभिव्यक्ति खाली अक्षरों द्वारा अलग किए गए बड़े अक्षरों के समूहों से मेल खाएगी। हालांकि यह एक बड़ी बात नहीं हो सकती है।
मिनीक्वायार्क

लगता है कि coonj को FASTA फाइलें पसंद हैं। ;)
एंड्रयू डलके

4

निम्नलिखित एक नियमित अभिव्यक्ति है जो पाठ के बहुस्तरीय ब्लॉक से मेल खाती है:

import re
result = re.findall('(startText)(.+)((?:\n.+)+)(endText)',input)

1

मेरी प्राथिमिकता।

lineIter= iter(aFile)
for line in lineIter:
    if line.startswith( ">" ):
         someVaryingText= line
         break
assert len( lineIter.next().strip() ) == 0
acids= []
for line in lineIter:
    if len(line.strip()) == 0:
        break
    acids.append( line )

इस बिंदु पर आपके पास स्ट्रिंग के रूप में someVaryingText और स्ट्रिंग्स की सूची के रूप में एसिड है। आप "".join( acids )एक स्ट्रिंग बनाने के लिए कर सकते हैं ।

मुझे मल्टीलाइन रीगेक्स की तुलना में यह कम निराशाजनक (और अधिक लचीला) लगता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.