1

我想要做的是逐行浏览文档,找到每个空白行,继续遍历直到我点击下一行文本,然后弹出该行。因此,例如,我想做的是:

第 1 段
这是一行。
这是另一条线。

这是空格后的一行,我想弹出!
这是下一行,我想保留。

这是我想弹出的另一行。

所以它会遍历每个空白行,直到它碰到下一个句子,并且只弹出那个句子,然后继续。我想我应该使用 re.split('\n') ,但我不确定。对不起,我没有要发布的代码,但我真的不知道从哪里开始任何帮助将不胜感激,谢谢!这是一个更大的代码的一部分,我已经工作了好几天并且已经弄清楚了这一点,所以我已经完成了大部分工作。

4

5 回答 5

1

到目前为止,最简单的新手解决方案可能是史蒂夫建议的方式:只需迭代行,并使用标志来跟踪最后一行是否为空行。

但是如果你想要一个更高层次的解决方案,你需要在更高层次上重新思考这个问题。您实际上要指定的是每个段落的第一行,但第一行,其中“段落”是由空行分隔的内容。正确的?

那么,你怎么能这样做呢?好吧,您可以'\n\n'像 on 一样轻松拆分 on \n。所以:

paragraphs = document.split('\n\n')
first_lines = [paragraph.partition('\n')[0] for paragraph in paragraphs]
popped_lines = first_lines[1:]

(我在这里使用partition而不是,split因为它只在第一个拆分'\n',其余部分不理会,并且因为它可以正确处理单行段落 - 这paragraph.split('\n', 1)不会。)

但是您不想要弹出行的列表,您想要除弹出行之外的所有内容的列表对吗?

paragraphs = document.split('\n\n')
first, rest = paragraphs[0], paragraphs[1:]
rest_edited = [paragraph.partition('\n')[1] for paragraph in rest]

如果你想把它变成一个文档:

all_edited = [first] + rest_edited
document_edited = '\n\n'.join(all_edited)

您可以通过使用切片分配来缩短它,尽管我不确定它是否具有可读性:

paragraphs = document.split('\n\n')
paragraphs[1:] = [paragraph.partition('\n')[1] for paragraph in paragraphs[1:]]
document_edited = '\n\n'.join(paragraphs)

正如 JF Sebastian 指出的那样,这个问题有点模棱两可。“空白行”是指“空行”还是“只有空格的行”?如果是后者,事情就有点复杂了,最简单的解决方案可能一个简单的正则表达式 ( r'\n\s*\n') 来分割成段落。


同时,如果您拥有的是一系列行(请注意,文件是一系列行!)而不是一个大字符串,您可以通过几种不同的方式完全不拆分。

例如,段落是一组非空行,对吧?因此,您可以使用该groupby函数来获取它们:

groups = itertools.groupby(lines, bool)

或者,如果“空白”并不意味着“空”:

groups = itertools.groupby(lines, lambda line: not line.strip())

请注意,这将为您(False, <sequence of lines>)提供每个段落和(True, <sequence of blank lines>)每个空白行。如果你想按原样保留空行,你可以——但如果你很高兴只用一个空行替换每一行空行(如果“空白”确实意味着“空”,那么你显然是这样),它可能是更容易丢弃空白段落:

paragraphs = (group for (key, group) in paragraphs if not key)

然后,您可以从除第一个组之外的所有元素中删除第一个元素,最后将这些组链接在一起形成一个大序列:

first = next(paragraphs)
edited_paragraphs = (itertools.islice(paragraph, 1) for paragraph in paragraphs)
edited_document = itertools.chain(first, *edited_paragraphs)

最后,如果您连续运行多个空行怎么办?好吧,首先你必须决定如何处理它们。如果你有两个空行,你会删除第二个吗?如果是这样,你是删除下一段的第一行(因为它最初是在一个空行之后),还是不删除(因为它之后的空行已经被删除了)?如果你连续三个呢?分裂'\n\n'会做一件事,分裂会做另一件事,还有另一'\n\s*\n'件事groupby……但在你知道你想要什么之前,当然不可能说哪个是“正确的”或如何“修复”其他的。

于 2013-03-14T22:38:31.450 回答
1

如果你这样做for line in filehandle:,它将遍历每一行。如果在上一行为空白时您的标志为真,您可以跳过下一行然后重置该标志。

于 2013-03-14T22:31:48.400 回答
1

我假设原始海报(OP)想要就地删除这些行,这意味着从文件中删除这些行。这是一个修改后的解决方案(我以前的解决方案不合时宜。谢谢 JF Sebastian 告诉我。

import fileinput

def remove_line_after_blank(filename, in_place_edit=False):
    previous_line = ''
    for line in fileinput.input(filename, inplace=in_place_edit):
        if not (previous_line == '\n' and line != '\n'):
            print line.rstrip()
        previous_line = line

if __name__ == '__main__':
    remove_line_after_blank('data.txt', in_place_edit=True)

讨论

  • 如果您不想修改原始数据文件,请删除, in_place_edit=True.
于 2013-03-14T22:36:22.063 回答
0

用于re.findall匹配字符串中的所有出现:

>>> text = """Paragraph 1
This is a line.
This is another line.

Here is a line after a space, which I want to pop!
Here is the next line, which I want to keep.

Here is another line I want to pop."""
>>> re.findall("\n\n+(.+)", text)
['Here is a line after a space, which I want to pop!', 'Here is another line I want to pop.']
>>> re.findall("\n\n+(.+)$", text, re.MULTILINE)
['Here is a line after a space, which I want to pop!', 'Here is another line I want to pop.']
于 2013-03-14T22:35:47.337 回答
-1

最简单的方法是将文本拆分为换行符:

lines = your_string.split("\n")

这会将其分解为一个数组(存储在 中lines),其中数组的每个元素都是单独的文本行。(如评论中所述,如果您已经有一个文件对象,则可以循环遍历它。)

然后你可以遍历每一行lines,检查换行符。如果你找到一个,你可以“弹出”下一个。(我不知道你所说的pop是什么意思,所以我只是让代码打印出你想要的行。)

for line in lines:
  if print_next_line:
     print(line)
     print_next_line = False

  if line == "":
    print_next_line = True
于 2013-03-14T22:33:11.377 回答