在python

时间:2016-02-25 00:15:04

标签: python regex parsing

我对这个问题有些困难。我需要删除波浪括号中包含的所有数据。

像这样:

Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there.

变为:

Hello there.

这是我的第一次尝试(我知道它很可怕):

while 1:
    firstStartBracket = text.find('{{')
    if (firstStartBracket == -1):
        break;
    firstEndBracket = text.find('}}')
    if (firstEndBracket == -1):
        break;
    secondStartBracket = text.find('{{',firstStartBracket+2);
    lastEndBracket = firstEndBracket;
    if (secondStartBracket == -1 or secondStartBracket > firstEndBracket):
        text = text[:firstStartBracket] + text[lastEndBracket+2:];
        continue;
    innerBrackets = 2;
    position = secondStartBracket;
    while innerBrackets:
        print innerBrackets;
        #everytime we find a next start bracket before the ending add 1 to inner brackets else remove 1
        nextEndBracket = text.find('}}',position+2);
        nextStartBracket = text.find('{{',position+2);
        if (nextStartBracket != -1 and nextStartBracket < nextEndBracket):
            innerBrackets += 1;
            position = nextStartBracket;
            # print text[position-2:position+4];
        else:
            innerBrackets -= 1;
            position = nextEndBracket;
            # print text[position-2:position+4];
            # print nextStartBracket
            # print lastEndBracket
            lastEndBracket = nextEndBracket;
        print 'pos',position;
    text = text[:firstStartBracket] + text[lastEndBracket+2:];

它似乎工作但内存耗尽很快。有没有更好的方法来做到这一点(希望用正则表达式)?

编辑:我不清楚,所以我再举一个例子。我需要允许多个顶级括号。

像这样:

Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there {{my }} friend.

变为:

Hello there friend.

7 个答案:

答案 0 :(得分:4)

您可以在此处使用pyparsing module。基于this answer的解决方案:

from pyparsing import nestedExpr


s = "Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there {{my }} friend."

expr = nestedExpr('{{', '}}')
result = expr.parseString("{{" + s + "}}").asList()[0]
print(" ".join(item for item in result if not isinstance(item, list)))

打印:

Hello there friend.

以下只有在只有一个顶级大括号时才有效。

如果你想用大括号本身删除双花括号里面的所有东西:

>>> import re
>>> 
>>> s = "Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there."
>>> re.sub(r"\{\{.*\}\} ", "", s)
'Hello there.'

\{\{.*\}\}会匹配双花括号,后跟任意次数的任意字符(故意留下"greedy"),然后是双花括号和空格。

答案 1 :(得分:4)

这是一个基于正则表达式/生成器的解决方案,适用于任意数量的大括号。此问题不需要实际堆栈,因为只涉及一种类型(井,对)令牌。 Autofac填充堆栈填充更复杂的解析器的角色。

MVC 6

更一般的要点......正则表达式中的捕获组是使level的输出中出现大括号的原因,否则你只能得到它们之间的东西。还有一些支持不匹配的括号。对于严格的解析器,应该引发异常,因为应该使用级别&gt;运行字符串的结尾。 0.对于松散的Web浏览器样式解析器,您可能希望将那些import re def _parts_outside_braces(text): level = 0 for part in re.split(r'(\{\{|\}\})', text): if part == '{{': level += 1 elif part == '}}': level = level - 1 if level else 0 elif level == 0: yield part x = 'Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there. {{ second set {{ of }} braces }}' print(''.join(_parts_outside_braces(x))) 显示为输出...

答案 2 :(得分:1)

请尝试以下代码:

import re

s = 'Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there'
m = re.search('(.*?) {.*}(.*)',s)
result = m.group(1) + m.group(2)
print(result)

答案 3 :(得分:1)

问题是您必须处理嵌套结构,这意味着正则表达式可能不够。但是,一个具有深度级别内存的简单解析器可能会被拯救 - 编写起来非常简单,只需存储即可 深度级别变为变量。

我只是在这里发布一种更加pythonic的方式来编写解决方案,这可能是一个很好的参考。

import re

def rem_bra(inp):
    i = 0
    lvl = 0
    chars = []
    while i < len(inp):
        if inp[i:i+2] == '{{':
            lvl += 1
            i += 1
        elif inp[i:i+2] == '}}':
            lvl -= 1
            i += 1
        else:
            if lvl < 1:
                chars.append(inp[i])
        i += 1
    result = ''.join(chars)

    # If you need no more contigious spaces, add this line:
    result = re.sub(r'\s\s+', r' ', result)

    return result


inp = "Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there."

print(rem_bra(inp))
>>> Hello there.

答案 4 :(得分:1)

为了更好的衡量,还有另一种解决方案。它首先找到并替换最左边的最内侧支撑,然后向外,向右移动。照顾多个顶级牙箍。

import re

def remove_braces(s):
    pattern = r'\{\{(?:[^{]|\{[^{])*?\}\}'
    while re.search(pattern, s):
        s = re.sub(pattern, '', s)
    return s

不是效率最高,但很短。

>>> remove_braces('Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there {{my }} friend.')
'Hello  there  friend.' 

答案 5 :(得分:1)

这个问题很有趣。这是我的尝试:

import re

def find_str(string):

    flag = 0

    for index,item in enumerate(string):

        if item == '{':
            flag += 1

        if item == '}':
            flag -= 1

        if flag == 0:
            yield index

s = 'Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there {{my }} friend.'

index = list(find_str(s))

l = [s[i] for i in index]

s = ' '.join(l)

re.sub('}\s+','',s)

'H e l l o t h e r e f r i e n d .'

答案 6 :(得分:0)

使用Python regex package可以使用recursive regex

{{(?>[^}{]+|(?0))*}} ?

或另一种变体(需要更多步骤)。

{{(?>[^}{]*(?R)?)*}} ?

粘贴(?0)(?R)模式。与regex.sub

一起使用
>>> import regex
>>> str = 'Hello {{world of the {{ crazy}} {{need {{ be}}}} sea }} there.'
>>> regex.sub(r'(?V1){{(?>[^}{]+|(?0))*}} ?', '', str)

(?V1)版本1的行为与Perl类似。无法测试,你需要尝试:)