【问题标题】:Proper way to search through line of text, re.findall() and re.search() both don't fully work通过文本行搜索的正确方法 re.findall() 和 re.search() 都不能完全工作
【发布时间】:2019-07-23 18:03:33
【问题描述】:

我的问题有点奇怪,也许有人可以提供一些指导。我有一行文本需要搜索并提取多个重复出现的字符串来填充数据框。给定以下行:

txt = "Name : 'red' Wire : 'R' Name : 'blue' Wire: 'B' Name : 'orange' Name: 'yellow' Wire : 'Y'"

我想通过正则表达式并提取完整的名称/电线对(在此示例中不是 Orange)。

预期输出

Name    Wire
red      R
blue     B
yellow   Y

代码

for line in txt:
    line = line.strip()
    a = re.search(r' Name : \'((?:(?![(]).)*)\'', line)
    if a:
        b = re.search(r' Wire : \'((?:(?![(]).)*)\'', line)
        if b:
            df = df.append({'Name' : a.group(1), 'Wire' : b.group(1)}, ignore_index=True)

此代码生成以下 df:

Name    Wire
red      R

这种行为是意料之中的,因为re.search() 只会运行直到它第一次找到有问题的项目。

好的,re.search() 不起作用,所以我会尝试 re.findall() 代替:

for line in txt:
    line = line.strip()
    a = re.findall(r' Name : \"((?:(?![(]).)*)\"', line)
    if a:
        b = re.findall(r' Wire : \"((?:(?![(]).)*)\"', line)
        if b:
            df = df.append({'Name' : a, 'Wire' : b}, ignore_index=True)

这将吐出以下df:

Name                                    Wire
['red','blue','orange','yellow']        ['R','B','Y']

这个数据框的问题是,现在我们不再知道 NameWire 相关联。如果 re.search() 没有到达 txt 行的末尾,是否有任何方法可以让 re.search() 在第一次命中后继续?任何人都对如何仅针对包含所有内容的元素(即“名称”AND“连线”)正则表达式文本行有任何创意吗?

【问题讨论】:

    标签: python regex pandas


    【解决方案1】:

    使用re.finditer 函数和特定的正则表达式模式:

    import pandas as pd
    import re
    
    txt = "Name : 'red' Wire : 'R' Name : 'blue' Wire: 'B' Name : 'orange' Name: 'yellow' Wire : 'Y'"
    pat = re.compile(r"Name\s*:\s*'(?P<Name>[^']+)'\s+Wire\s*:\s*'(?P<Wire>[^']+)'")
    items = [m.groupdict() for m in pat.finditer(txt)]
    df = pd.DataFrame(items)
    print(df)
    
    • (?P&lt;Name&gt;[^']+) - 命名子组 被“翻译”为m.groupdict() 对象

    输出:

        Name Wire
    0     red    R
    1    blue    B
    2  yellow    Y
    

    【讨论】:

    • 感谢您的帮助!:)
    【解决方案2】:

    我不习惯pandas,但我通过列表理解实现了这一点,也许会对你有所帮助:

    import re
    
    def populateNameWire(content):
        pairs = re.findall(r'Name *: *\'(?P<name>\w+)\' Wire *: *\'(?P<wire>\w+)\'', content)
        return [{'Name': name, 'Wire': wire} for name, wire in pairs]
    
    populateNameWire("Name : 'red' Wire : 'R' Name : 'blue' Wire: 'B' Name : 'orange' Name: 'yellow' Wire : 'Y'")`
    
    [{'Name': 'red', 'Wire': 'R'}, {'Name': 'blue', 'Wire': 'B'}, {'Name': 'yellow', 'Wire': 'Y'}]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多