【问题标题】:Regex search up to first instance Python正则表达式搜索到第一个实例 Python
【发布时间】:2018-06-09 06:05:12
【问题描述】:

知道还有很多其他类似的问题,但我已经建立了其他答案但没有成功。 我挖了hereherehereherehere 但是这个question 最接近我想要做的事情,但是它在 php 中,我正在使用 python3

我的目标是从正文中提取子字符串。 正文已格式化:

**Header1**   
thing1  
thing2  
thing3  
thing4 

**Header2**  
dsfgs  
sdgsg  
rrrrrr 

**Hello Dolly**  
abider  
abcder  
ffffff

etc.

在 SO 上格式化很困难。但在实际文本中,没有空格,每行只有换行符。

我想要 Header2 下的内容,所以目前我有:

found = re.search("\*\*Header2\*\*\n[^*]+",body)
        if found:
            list = found.group(0)
            list = list[11:]
            list = list.split('\n')
            print(list)

但这会返回“无”。我尝试过的各种其他正则表达式也没有工作,或者抓取太多(所有剩余的标题)。 对于它的价值,我也尝试过: \*\*Header2\*\*.+?^\**$ \*\*Header2\*\*[^*\s\S]+\*\* 和大约 10 个其他排列。

【问题讨论】:

  • \n**Header** 之后不存在,因为有空格。
  • @ctwheels 删除 \n 解决了我的问题!如果您想将其发布为答案,我会接受它

标签: python regex python-3.x search python-3.5


【解决方案1】:

简介

您的模式 \*\*Header2\*\*\n[^*]+ 不匹配,因为您的行 **Header2** 在换行符之前包含尾随空格。添加* 就足够了,但我还在下面添加了其他选项。


代码

See regex in use here

\*{2}Header2\*{2} *\n([^*]+)

或者,您还可以使用以下正则表达式(它还允许您捕获其中包含 * 的行,只要它们与您的标题格式不匹配 ^\*{2}[^*]*\*{2} - 它还可以很好地从标题下的最后一个元素 - 使用 im 标志):

See regex in use here

^\*{2}Header2\*{2} *\n((?:(?!^\*{2}[^*]*\*{2}).)*?)(?=\s*^\*{2}[^*]*\*{2}|\s*\Z)

用法

See code in use here

import re

regex = r"\*{2}Header2\*{2}\s*([^*]+)\s*"

test_str = ("**Header1**   \n"
    "thing1  \n"
    "thing2  \n"
    "thing3  \n"
    "thing4 \n\n"
    "**Header2**  \n"
    "dsfgs  \n"
    "sdgsg  \n"
    "rrrrrr \n\n"
    "**Hello Dolly**  \n"
    "abider  \n"
    "abcder  \n"
    "ffffff")

print(re.search(regex, test_str).group(1))

说明

该模式实际上与 OP 的原始模式相同。我做了一些小改动,让它更好地执行并获得 OP 所期望的结果。

  1. \*\* 更改为 \*{2}:对性能进行了非常小的调整
  2. \n 更改为 *\n:在换行符之前考虑行尾的额外空格
  3. ([^*]+):将 OP 期望的内容捕获到捕获组 1 中

【讨论】:

    【解决方案2】:

    你可以使用

    ^\*\*Header2\*\*.*[\n\r]
    (?P<content>(?:.+[\n\r])+)
    

    使用multilineverbose 修饰符,请参阅a demo on regex101.com
    之后,只需获取content 中的内容(即使用re.finditer())。


    分解这个说:
    ^\*\*Header2\*\*.*[\n\r]    # match **Header2** at the start of the line 
                                # and newline characters
    (?P<content>(?:.+[\n\r])+)  # afterwards match as many non-null lines as possible
    


    Python:
    import re
    rx = re.compile(r'''
        ^\*\*Header2\*\*.*[\n\r]
        (?P<content>(?:.+[\n\r])+)
        ''', re.MULTILINE | re.VERBOSE)
    
    for match in rx.finditer(your_string_here):
        print(match.group('content'))
    


    我有一种感觉,你甚至想在段落之间允许空行。如果是,则将表达式更改为
    ^\*\*Header2\*\*.*[\n\r]
    (?P<content>[\s\S]+?)
    (?=^\*\*)
    

    也请参阅a demo for the latter on regex101.com

    【讨论】:

    • 我的代码永远不会在这个上输入 for 语句:/
    【解决方案3】:

    你可以试试这个:

    import re
    s = """
    **Header1**   
    thing1  
    thing2  
    thing3  
    thing4 
    
    **Header2**  
    dsfgs  
    sdgsg  
    rrrrrr 
    
    **Hello Dolly**  
    abider  
    abcder  
    ffffff
    """
    new_contents = re.findall('(?<=\*\*Header2\*\*)[\n\sa-zA-Z0-9]+', s) 
    

    输出:

    ['  \ndsfgs  \nsdgsg  \nrrrrrr \n\n'] 
    

    如果你想从输出中删除特殊字符,你可以试试这个:

    final_data = filter(None, re.split('\s+', re.sub('\n+', '', new_contents[0])))
    

    输出:

    ['dsfgs', 'sdgsg', 'rrrrrr']
    

    【讨论】:

    • 这将为我返回一个空数组,用于 'new_contents' :/
    • @Acoustic77 你是在读取文本文件吗?我通过从您发布的输入创建一个多行字符串来实现上述结果。
    猜你喜欢
    • 1970-01-01
    • 2013-05-18
    • 2014-11-12
    • 1970-01-01
    • 2015-03-24
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多