【问题标题】:Remove leading/ending and internal multiple spaces but NOT tabs, newlines, or return characters, in Python在 Python 中删除前导/结束和内部多个空格,但不删除制表符、换行符或返回字符
【发布时间】:2017-12-02 08:00:50
【问题描述】:

Python remove all whitespace in a string 问题的答案显示了分别从 Python 中的字符串中删除前导/结尾、重复和所有空格的不同方法。但是 strip() 删除制表符和换行符,而 lstrip() 只影响前导空格。使用 .join(sentence.split()) 的解决方案似乎也删除了 Unicode 空白字符。

假设我有一个字符串,在本例中是使用 Scrapy 从网站上抓取的,如下所示:

['\n                        \n                    ',
         '\n                        ',
         'Some text',
         ' and some more text\n',
  ' and on another a line some more text', '
                ']

当我在其他上下文中使用换行符时,它会保留文本的格式,但是所有额外的空间都是令人讨厌的。 如何删除所有前导、结尾和重复的内部空格,同时保留换行符(除了任何 \r 或 \t 字符,如果有的话)?

我想要的结果(在我加入各个字符串之后)将是:

['\n\n\nSome text and some more text\nand on another line some more text']

没有提供示例代码,因为到目前为止我尝试的只是上面引用的页面上的建议,它得到了我试图避免的结果。

【问题讨论】:

    标签: python scrapy whitespace


    【解决方案1】:

    在这种情况下,str.strip() 不会帮助您(即使您使用 " " 作为参数,因为它不会删除内部的空格,只会在字符串的开头/结尾处,它会删除"and" 之前的一个空格也是如此。

    改为使用正则表达式从字符串中删除 2 个或更多空格:

    l= ['\n                        \n                    ',
             '\n                        ',
             'Some text',
             ' and some more text\n',
      ' and on another a line some more text']
    
    import re
    
    result = "".join([re.sub("  +","",x) for x in l])
    
    print(repr(result))
    

    打印:

    '\n\n\nSome text and some more text\n and on another a line some more text'
    

    编辑:如果我们将正则表达式应用于每一行,我们无法检测到 \n 在某些情况下,如您所述。因此,替代且更复杂的解决方案是在应用正则表达式之前加入字符串,并应用更复杂的正则表达式(请注意,我更改了字符串的测试列表以添加更多极端情况):

    l= ['\n                        \n                    ',
             '\n                        ',
             'Some text',
             ' and some more text \n',
      '\n and on another a line some more text ']
    
    import re
    
    result = re.sub("(^ |(?<=\n) |  +| (?=\n)| $)","","".join(l))
    
    print(repr(result))
    

    打印:

    '\n\n\nSome text and some more text\n\nand on another a line some more text'
    

    现在正则表达式中有 5 个案例将被删除:

    • 以一个空格开始
    • 换行符后的空格
    • 2 个或更多空格
    • 空格后跟换行符
    • 以一个空格结尾

    事后诸葛亮:看起来(并且确实)很复杂。 is 毕竟有一个非正则表达式解决方案,它给出完全相同的结果(如果单词之间没有多个空格):

    result = "\n".join([x.strip(" ") for x in "".join(l).split("\n")])
    print(repr(result))
    

    只需加入字符串,然后根据换行符拆分,应用strip" " 作为参数以保留标签,然后根据换行符再次加入。

    re.sub(" +"," ",x.strip(" ")) 链接以处理单词之间可能的双空格:

    result = "\n".join([re.sub("  +"," ",x.strip(" ")) for x in "".join(l).split("\n")])
    

    【讨论】:

    • 这很有帮助,几乎完全回答了它 - 除了如果一个空格开始一个新行,就像这里的例子一样,它不会被剥离。
    • @NFB:现在答案看起来很完整,现在甚至有 2 个替代方案 :)
    • 这完全解决了原始示例,但是它确实有一个我的示例字符串未说明的意外效果。如果单词之间有多个空格,它会将它们减少到根本没有空格,而不是只有一个空格。但是,我将其标记为已回答,因为它确实解决了原始示例。还有很多可能的解决方案。谢谢!
    • 除非我遗漏了什么,否则我仍然会删除双空格,而不是替换为单个空格。哪个代码 sn-p 被修复以将许多空格替换为一个,较长的一个或第二个(较短的)一个?
    【解决方案2】:

    如果你愿意,你也可以通过内置的字符串操作来完成整个事情。

    l = ['\n                        \n                    ',
         '\n                        ',
         'Some text',
         ' and some more text\n',
         ' and on another a      line some more text',
         '              ']
    
    
    def remove_duplicate_spaces(l):
        words = [w for w in l.split(' ') if w != '']
        return ' '.join(words)
    
    lines = ''.join(l).split('\n')
    formatted_lines = map(remove_duplicate_spaces, lines)
    u = "\n".join(formatted_lines)
    
    print(repr(u))
    

    给予

    '\n\n\nSome text and some more text\nand on another a line some more text'
    

    您也可以将整个内容折叠成一条线:

    s = '\n'.join([' '.join([s for s in x.strip(' ').split(' ') if s!='']) for x in ''.join(l).split('\n')])
    
    # OR
    
    t = '\n'.join(map(lambda x: ' '.join(filter(lambda s: s!='', x.strip(' ').split(' '))), ''.join(l).split('\n')))
    

    【讨论】:

      猜你喜欢
      • 2013-05-10
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多