Python - 在括号内读取单个“块”

时间:2012-10-17 08:51:38

标签: python

我正在尝试用Python编写一个程序,它为一段代码执行各种任务。我已经完成了大部分工作,但其中一个令我困惑。我不太了解能够有效搜索这个问题的帮助,所以我在这里求助。

我需要创建一个进程,将括号中的任何内容读作单个“块”。然后,如果'block'包含特定的单词或短语,python代码将删除它。

示例(简化)文本文件内容:

...
entity
{
    "id" "38794"
    "classname" "info_player_teamspawn"
}
entity
{
    "id" "38795"
    "classname" "func_detail"
    solid
}
entity
{
    "id" "38796"
    "classname" "path_track"
}
...

在此示例中,将列出数千个这样的实体。我希望python代码删除任何包含单词'solid'的括号内的任何内容(包括'实体'前言),即: 这将是结果:

...
entity
{
    "id" "38794"
    "classname" "info_player_teamspawn"
}
entity
{
    "id" "38796"
    "classname" "path_track"
}
...

不需要更正ID。我们不需要担心这一点。

我希望我能够很好地解释我的问题,我希望有一个可行的解决方案。如果有人想要一个行话库,我可以用来帮助解释或研究我可能遇到的任何其他问题,这也是值得赞赏的!

非常感谢提前!

5 个答案:

答案 0 :(得分:1)

可以使用单个正则表达式完成所有操作。然而,这很快变得不可读,特别是当你跨越多行时(我猜你可能有其他模式你可能想要删除)。

我会将问题分成两部分:

首先,使用此正则表达式查找所有实体块:

p = re.compile(r'entity\s*{(.*?)}')

然后定义替换函数进行替换。

def remove_solid(match):
    text = match.groups(0)
    if text.find('solid') != -1:
        return ''
    else
        return text 

像这样将这两个连在一起

output = p.sub(remove_solid, input)

答案 1 :(得分:1)

首先,让我们编写一个生成标题("实体")及其各自块的生成器:

def blocks(filename):
    title, block = '', None
    with open(filename) as fp:
        for line in fp:
            if '{' in line:
                block = line
            elif block is not None:
                block += line
            else:
                title = line
            if '}' in line:
                yield title, block
                title, block = '', None

然后读取块并输出通过测试的那些:

for title, block in blocks('input.txt'):
    if 'solid' not in block:
        print title, block

答案 2 :(得分:0)

您可以使用正则表达式(正则表达式)搜索以下模式,并使用换行符或空格替换匹配的文本。

import re

[...]
output = re.sub(r'entity\n{[\w\s\n"]*solid[\w\s\n"]*\n}\n', '', input)
[...]

答案 3 :(得分:0)

怎么样:

 re.sub("entity\s*{[^}]*solid\s*}",'',yourString)

答案 4 :(得分:0)

这是一个非正则表达式解决方案。它可能更冗长,但也更直观。

input = open("a.txt", "rb")
output = open("b.txt", "wb") # an empty file for output

def filter_block(instream, outstream, keyword):
    block_buffer = []
    in_block = False
    dump_block = False
    for line in instream:                 # <- Iterate through the lines of the input
        line = line.rstrip()
        block_buffer.append(line)         # <- Keep the block of text in memory

        line_text = line.strip()
        if line_text == "{":
            in_block = True
        elif line_text == keyword and in_block:            # <- Check if this block
            dump_block = True                              #    needs to be dumped
        elif line_text == "}":
            if not dump_block:                             # <- If not, 
                outstream.write("\n".join(block_buffer))   # <- keep it.
                #print "\n".join(block_buffer)

            block_buffer = []                              # <- Flush buffer, continue
            in_block = dump_block = False



filter_block(input, output, "solid")