如何提取最接近的标点符号之前的子字符串?

问题描述 投票:0回答:2

从使用 Python 3.12 的文本文件中,如何从具有多个括号的行中提取子字符串:

line1: 'group(something)'
line2: 'other(something) and group(something,something,something) and not group(something,something)'

我只对“group()”或“not group()”中的“某物”感兴趣。

def find_within(search_in, search_for, until):
    return search_in[search_in.find(search_for) + len(search_for) : search_in.find(until)]

group1 = find_within(line1, 'group(', ')')        # extracting group from the first line
group2 = find_within(line2, 'and group(', ')')    # extracting group from the second line
not_group = find_within(line2, 'not group(', ')')    # extracting 'not group' from the second line

此函数可以处理从仅具有单个“group()”(如 line1)的行中进行提取,但不能处理从具有多个项目(如 line2)的行中进行提取(它将返回 null)。我尝试用

.find()
替换最后一个
.rfind()
:

def find_within(search_in, search_for, until):
    return search_in[search_in.find(search_for) + len(search_for) : search_in.rfind(until)]

但是输出是:

'某事,某事,某事)而不是组(某事,某事'

虽然我期待:

“某事,某事,某事”

.find()
查找括号的第一次出现,因此当我从字符串中间的“group(something)”中查找“something”时,
.find()
会查看前面一对括号中的右括号'group(something)',因此返回 ''。并且
.rfind()
查找最后一次出现的括号,因此提取直到最后一个括号的所有内容。

有更好的方法使用

.find()
还是我需要正则表达式?

python python-3.x text-parsing
2个回答
0
投票

我认为您可能缺少的是,您可以给

str.find()
第二个可选整数参数(
str.find(target, offset)
)来告诉您要从哪里开始搜索。

因此,在下面的示例中,我们使用

start = 0
作为字符串的开头

如果找到目标字符串,我们将

start
前进
offset
,以指向刚刚过去 '(' 字符的字符。然后我们从该位置向前搜索,找到下一个 ')' 字符,即我们的
stop
位置

那么括号里的内容就是从

stop
start
的切片。 在我的示例中,我将
contents
附加到
list
,但您可以将其打印出来,或者您需要的任何内容

最终

str.find()
将返回-1,表示没有进一步的匹配,因此我们从函数返回

text = "group(a, b, c) and group(d, e, f) and not group(g, h, i)"    


def findit(target, text):
    
    """look for target followed by (
       save the text following the ( until the next )
       append that text to results
       when target doesn't match any more return results"""
       
    results = []
    target += '('    #add open parenthesis after target
    offset = len(target)
    
    start = 0
    while True:
        start = text.find(target, start)
        #print(start)
        if start == -1:
            break
        
        start += offset
        stop = text.find(')', start)
        contents = text[start:stop]
        results.append(contents)
        
    return results

print("\ngroup")
print(findit('group', text))

print("\nand group")
print(findit('and group', text))

print("\nnot group")
print(findit('not group', text))

该程序将产生以下输出:

group
['a, b, c', 'd, e, f', 'g, h, i']

and group
['d, e, f']

not group
['g, h, i']

0
投票

您可以使用模式来查找预期输出:

\b(group)\s*\(([^)]+)\)|\s*(\band\s+group)\(([^)]+)\)|\s*(\band\s+not\s+group)\(([^)]+)\)|\s*\b(other)\(([^)]+)\)

代码:

import re


def _find(p, s):
    return re.findall(p, s)


p = r'\b(group)\s*\(([^)]+)\)|\s*(\band\s+group)\(([^)]+)\)|\s*(\band\s+not\s+group)\(([^)]+)\)|\s*\b(other)\(([^)]+)\)'
s = """
line1: 'group(something)'
line2: 'other(something) and group(something,something,something) and not group(something,something)'
I'
"""
print(_find(p, s))


打印

[('group', 'something', '', '', '', '', '', ''), ('', '', '', '', '', '', 'other', 'something'), ('', '', 'and group', 'something,something,something', '', '', '', ''), ('', '', '', '', 'and not group', 'something,something', '', '')]


注释

  • 有 8 个捕获组:四组是键,四组是值。
  • \(([^)]+)\)
    :这四组就是数值。

编辑

您可以使用简单的模式并获取所有键和值,然后继续执行文本处理任务:

import re


def _find(p, s, as_dict=False):
    matches = re.findall(p, s)
    if as_dict:
        return {m[0].strip(): m[1] for m in matches}
    return matches


p = r"\s*([^(']+)\s*\(([^)]+)\)"
s = """
line1: 'group(something)'
line2: 'other(something) and group(something,something,something) and not group(something,something)'
I'
"""

print(_find(p, s))

print(_find(p, s, as_dict=True))

打印

[('group', 'something'), ('other', 'something'), ('and group', 'something,something,something'), ('and not group', 'something,something')]
{'group': 'something', 'other': 'something', 'and group': 'something,something,something', 'and not group': 'something,something'}

详情

第二种模式非常简单:

  • ([^(']+)
    :捕获组 1 找到密钥。
  • \s*\(([^)]+)\)
    :捕获组 2 找到值。
  • [^(']+
    :表示允许使用所有字符,除了(即
    ^
    )这两个
    [(']
    ,然后一次或多次(即
    +
    )。
  • ([^)]+)
    :表示允许使用所有字符,除了(即
    ^
    )一个字符,即字符类中的
    )
    (即
    []
    )。
© www.soinside.com 2019 - 2024. All rights reserved.