web-dev-qa-db-ja.com

複数行のテキストブロックに一致する正規表現

複数の行にまたがるテキストと照合するときに、Python正規表現を取得するのに少し苦労しています。サンプルテキストは( '\ 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」部分と、1行のキャプチャで2行下にある大文字のテキストのすべての行(後で改行文字を削除できます)の2つのことをキャプチャしたいと思います。私はいくつかのアプローチで試しました:

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

そして、運のないここの多くのバリエーション。最後の1つはテキストの行と1つずつ一致しているようですが、これは私が本当に望んでいるものではありません。最初の部分は問題なくキャッチできますが、大文字のテキストの4〜5行はキャッチできないようです。 match.group(1)がsome_Varying_Textになり、group(2)がline1 + line2 + line3 + etcになり、空の行が検出されるようになります。

好奇心が強い人は、タンパク質を構成するアミノ酸の配列であると考えられています。

84
Jan

これを試して:

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

あなたの最大の問題は、^$アンカーが改行と一致することを期待しているが、そうではないことだと思います。複数行モードでは、^はすぐに位置に一致します後続改行、$はすぐに位置に一致します改行。

また、改行は改行(\ n)、復帰(\ r)、復帰+改行(\ r\n)で構成できることに注意してください。ターゲットテキストが改行のみを使用していることが確実でない場合は、このより包括的なバージョンの正規表現を使用する必要があります。

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

ところで、ここではDOTALL修飾子を使用したくありません。あなたはドットがすべてに一致するという事実に頼っています除く改行。

105
Alan Moore

これは動作します:

>>> 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は、「2つの改行に達するまで、できるだけ少ない文字に一致する(すべての文字が許可される)」ことを意味します。結果(改行なし)は最初のグループに入れられます。
  • [A-Z]+\nは、「改行に達するまで、できるだけ多くの大文字に一致することを意味します。これは、私がtextlineと呼ぶものを定義します。
  • ((?:textline)+)は、1つ以上のtextlinesと一致するが、各行をグループに入れないことを意味する。代わりに、all thetextlinesを1つのグループに入れます。
  • 最後に二重改行を強制する場合は、正規表現に最後の\nを追加できます。
  • また、どのタイプの改行を取得するのかわからない場合(\nまたは\rまたは\r\n)、\nのすべての出現箇所を置き換えることで正規表現を修正します。 (?:\n|\r\n?)によって。
20
MiniQuark

各ファイルにアミノ酸のシーケンスが1つしかない場合、正規表現はまったく使用しません。このようなもの:

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
6
MiniQuark

見つける:

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

\ 1 = some_varying_text

\ 2 =すべてのCAPSの行

編集(これが機能することの証明):

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])
3
Jason Coon

以下は、複数行のテキストブロックに一致する正規表現です。

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

私の好み。

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 )を実行して、単一の文字列を作成できます。

これは、複数行の正規表現よりもイライラが少ない(そして柔軟性が高い)ことがわかりました。

1
S.Lott