即使单个项目,多行正则表达式也无法匹配

时间:2014-12-03 00:21:26

标签: python regex python-3.x

我试图在一堆大文本文件中搜索特定信息。

#!/usr/bin/env python
# pythnon 3.4
import re
sometext = """
    lots
    of
    text here
    Sentinel starts
    --------------------
    item_one               item_one_result
    item_two               item_two_result
    --------------------
    lots
    more
    text here
    Sentinel starts
    --------------------
    item_three               item_three_result
    item_four                item_four_result
    item_five                item_five_result
    --------------------
    even
    more
    text here
    Sentinel starts
    --------------------
    item_six                item_six_result
    --------------------
    """
sometextpattern = re.compile( '''.*Sentinel\s+starts.*$                           # sentinel
                                 ^.*-+.*$                                         # dividing line
                                 ^.*\s+(?P<itemname>\w+)\s+(?P<itemvalue>\w+)\s+  # item details
                                 ^.*-+.*$                                         # dividing line                                  
                              ''', flags = re.MULTILINE | re.VERBOSE)
print( re.findall( sometextpattern, sometext ) )

单独地,哨兵和分界线自己匹配。我如何一起工作?即我想要打印:

[('item_one','item_one_result'),('item_two','item_two_result'),('item_three','item_three_result'),('item_four','item_four_result'),('item_five','item_five_results'),('item_six','item_six_results')]

3 个答案:

答案 0 :(得分:1)

正则表达式多行匹配标记仅使^$分别匹配每行的开头和结尾。如果要匹配多行,则需要添加空格元字符'\\s'以匹配换行符。

.*Sentinel\s+starts.*$\s
^.*-+.*$\s
^.*\s+(?P<itemname>\w+)\s+(?P<itemvalue>\w+)\s+
^.*-+.*$

Regular expression visualization

Debuggex Demo


您使用的字符串也没有必需的字符串转义。我建议改用r''类型的字符串。这样你就不必逃避反斜杠了。

答案 1 :(得分:1)

按顺序使用四个捕获组,在列表中打印所需的文本。

>>> import regex
>>> text = """    lots
    of
    text here
    Sentinel starts
    --------------------
    item_one               item_one_result
    item_two               item_two_result
    --------------------
    lots
    more
    text here
    Sentinel starts
    --------------------
    item_three               item_three_result
    item_four                item_four_result
    item_five                item_five_result
    --------------------
    even
    more
    text here
    Sentinel starts
    --------------------
    item_six                item_six_result
    --------------------"""
>>> regex.findall(r'(?:(?:\bSentinel starts\s*\n\s*-+\n\s*|-+)|(?<!^)\G) *(\w+) *(\w+)\n*', text)
[('item_one', 'item_one_result'), ('item_two', 'item_two_result'), ('item_three', 'item_three_result'), ('item_four', 'item_four_result'), ('item_five', 'item_five_result'), ('item_six', 'item_six_result')]

\s*匹配零个或多个空格字符,\S+匹配一个或多个非空格字符。 \G在上一场比赛结束时或第一场比赛的字符串开头处断言位置。

DEMO

答案 2 :(得分:1)

试试这些正则表达式:

for m in re.findall(r'(?:Sentinel starts\n[-\n]*)([^-]+)', sometext, flags=re.M ):
    print(list(re.findall(r'(\w+)\s+(\w+)', m)))

它为您提供了一个关键的值元组列表:

# [('item_one', 'item_one_result'), ('item_two', 'item_two_result')]
# [('item_three', 'item_three_result'), ('item_four', 'item_four_result')]

因为文本有尾随空格,所以更改for语句中的正则表达式:

r'(?:Sentinel starts\s+-*)([^-]*\b)'