1

我有一个文本文件。我需要找到以任意模式开头的文件的一部分,然后捕获模式之间的所有内容,它正在关闭括号。此模式可能在文件中出现多次。“开始(”将始终出现在模式之前。示例:

start
(
    pattern
    (
        stuff,
        stuff,
            randomThing
            (
                random stuff
            )
    )
)
start
(
    notThePattern
    (
        otherStuff,
        otherStuff
    )
)
start
(
    pattern
    (
        moreStuff,
        moreStuff
    )
)

我想得到 [Start(Pattern(stuff,stuff,randomThing(random stuff))), Start(Pattern(moreStuff,moreStuff))]。

我这样做的方式是使用以下代码:

def myFunct(pattern, input):
    allElements = []
    match = re.search("start\s*?\(\s*?" + pattern, input)
    while (match != None):
        index = match.start()
        element = getElementEndIndex(line[index:])
        allElements.append(element)
        input = input[index+len(element):]
        match = re.search("start\s*?\(\s*?" + pattern, input)

getElementEndIndex 只是使用堆栈来查找结束括号和它的索引。

这是唯一的方法吗?可以只用一个正则表达式来解决吗?如果没有,是否有更好的方法来运行我拥有的正则表达式?

模式可以在“开始”部分中出现多次。但是,开始不能在另一个开始部分内。

start
(
    pattern
    ()
    blah
    ()
    pattern
    ()
)

是可能的,但是

start
(
    pattern
    ()
    start
    ()
)

不是

4

5 回答 5

1

因此,如果“stuff”包含括号,则无法将其与常规语言匹配,因为您需要开始计算左右括号。

但是,如果东西没有。你可以做类似模式换行符((“not)”或换行符)一次或多次)

所以看起来像

/pattern\n(\([^)]\+\|\n\)\+)/

如果不是 this 的副本,这也是相似。所以也许最好的解决方案是使用pyparsing来形成各种 pda。

如果您可以控制编写这些内容的任何内容,那么您将来可能会选择像json这样的众所周知的格式,这样您就可以利用已经设置好的工具来解决此类问题。它更具表现力和便携性。

于 2013-10-16T16:32:32.030 回答
0

有没有更好的方法来找到用正则表达式找到的表达式的右括号?

是的。不要使用正则表达式。

具体来说,您想使用某种解析器;使用实际的数据结构比专门的正则表达式匹配的文本要容易得多。

编写解析器是一门需要比 SO 答案更多的信息的主题(我不得不承认这是我知识的一个弱点)。更简单的解决方案是将您的数据调整为已定义的格式,并使用该格式的解析器。常用选项包括JSONINIUnix shell

如果您必须编写自己的解析器,您可能需要研究pyPEGparsimonious之类的东西,或者这个广泛列表中的任何其他工具。

于 2013-10-16T19:46:10.953 回答
0

你说:

我想得到 [Start(Pattern(stuff,stuff)), Start(Pattern(moreStuff,moreStuff)) ]。

如果是这样,那很容易:

import re

txt='''\
start
(
    pattern
    (
        stuff,
        stuff
    )
)
start
(
    notThePattern
    (
        otherStuff,
        otherStuff
    )
)
start
(
    pattern
    (
        moreStuff,
        moreStuff
    )
)
'''
rst=[]
for m in re.finditer(r'^(start.*?)(?=start|\Z)', txt, re.S | re.M):
    rst.append(m.group(1).replace('\n','').replace(' ',''))

print rst

印刷:

['start(pattern(stuff,stuff))', 
 'start(notThePattern(otherStuff,otherStuff))', 
 'start(pattern(moreStuff,moreStuff))']

那是你要的吗?这并不能验证括号的数量是否正确。

于 2013-10-16T17:17:12.503 回答
0

这是一个开始。您将需要按摩列表项并预先添加单词start以获得您需要的确切格式。

import re
s = """start
(
    pattern
    (
        stuff,
        stuff
    )
    blah
    (
        baz,
        baz
     )
    pattern
    (
        xtrastuff,
        xtrastuff
    )
)
start
(
    notThePattern
    (
        otherStuff,
        otherStuff
    )
)
start
(
    pattern
    (
        moreStuff,
        moreStuff
    )
)"""
# remove all whitespace
s1 = re.sub('\s','',s)
## 'start(pattern(stuff,stuff)blah(bazbaz)pattern(xtrastuff,xtrastuff))start(notThePattern(otherStuff,otherStuff))start(pattern(moreStuff,moreStuff))'

# stuff you are looking for
pattern = 'pattern.*?\)'

# find all of the start 'items' with pattern in them
start_pattern = '(start\(' + pattern + '\))'
starts = re.findall(start_pattern, s1)
## ['start(pattern(stuff,stuff)blah(baz,baz)pattern(xtrastuff,xtrastuff))', 'start(pattern(moreStuff,moreStuff))']

# extract stuff you are looking for from all the 'start' items
for start in starts:
    stuff =  re.findall(pattern, start)
    print stuff
    print '*'*8

>>> 
['pattern(stuff,stuff)', 'pattern(xtrastuff,xtrastuff)']
********
['pattern(moreStuff,moreStuff)']
********
于 2013-10-16T18:40:11.750 回答
0

来自 LilyPond convert-ly 实用程序(由我自己编写/版权所有,所以我可以在这里展示它):

def paren_matcher (n):
    # poor man's matched paren scanning, gives up
    # after n+1 levels.  Matches any string with balanced
    # parens inside; add the outer parens yourself if needed.
    # Nongreedy.
    return r"[^()]*?(?:\("*n+r"[^()]*?"+r"\)[^()]*?)*?"*n

convert-ly 倾向于在其正则表达式中使用它作为 paren_matcher (25),这对于大多数应用程序来说可能是矫枉过正的。但随后它使用它来匹配 Scheme 表达式。

于 2014-04-02T11:22:55.200 回答