代码之家  ›  专栏  ›  技术社区  ›  Jan

匹配多行文本块的正则表达式

  •  154
  • Jan  · 技术社区  · 17 年前

    \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
    • capture(我稍后可以去掉换行符)。

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

    …还有很多变体,但运气不佳。最后一个似乎与文本行一一匹配,这不是我真正想要的。我可以抓住第一部分,没问题,但我似乎无法抓住4-5行大写文本。 match.group(1) some Varying Text group(2) 直到遇到空行为止。

    如果有人好奇,它应该是构成蛋白质的氨基酸序列。

    7 回复  |  直到 3 年前
        1
  •  134
  •   Alan Moore Chris Ballance    5 年前

    试试这个:

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

    ^ $ 立即匹配位置 立即匹配位置 换行符。

    还要注意,换行符可以由换行符组成( \n \r \r\n

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

    顺便说一句,你不想在这里使用DOTALL修饰符;你所依赖的事实是,这个点与所有东西都匹配

        2
  •  27
  •   MiniQuark    17 年前

    >>> 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 意思是“尽可能少地匹配字符(允许所有字符),直到达到两个新行”。结果(不含换行符)被放入第一组。
    • [A-Z]+\n 意思是“在换行之前,尽可能多地匹配大写字母。这定义了我所说的 .
    • ((?: )+) 指匹配一个或多个 但不要把每一行都放在一个组中。相反,把
    • 你可以添加一个final \n
    • 此外,如果你不确定你会得到什么类型的换行符( n \r \r\n n (?:\n|\r\n?) .
        3
  •  12
  •   Grant Miller    7 年前

    import re
    result = re.findall('(startText)(.+)((?:\n.+)+)(endText)',input)
    
        4
  •  5
  •   MiniQuark    17 年前

    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
    
        5
  •  4
  •   Jason Coon    17 年前

    有时,直接在字符串中指定标志会很舒服,因为 inline-flag :

    "(?m)^A complete line$".
    

    assertRaisesRegex 那样的话,你就不需要了 import re

        6
  •  1
  •   S.Lott    17 年前

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

    \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)]
    #NOTE can be sorter with matches = re.findall(pattern, text, re.MULTILINE)
    
    for m in matches:
        print 'Name: %s\nSequence:%s' % (m[0], m[1])