【问题标题】:How do I trim whitespace?如何修剪空白?
【发布时间】:2010-11-14 04:56:20
【问题描述】:

是否有一个 Python 函数可以从字符串中修剪空白(空格和制表符)?

例如:\t example string\t → example string

【问题讨论】:

标签: python string whitespace trim strip


【解决方案1】:

两边的空格使用str.strip:

s = "  \t a string example\t  "
s = s.strip()

右侧的空格使用rstrip:

s = s.rstrip()

对于左侧的空格lstrip:

s = s.lstrip()

正如thedz 指出的那样,您可以提供一个参数来将任意字符剥离到任何这些函数中,如下所示:

s = s.strip(' \t\n\r')

这将删除字符串左侧、右侧或两侧的任何空格、\t、\n 或 \r 字符。

上面的示例只从字符串的左侧和右侧删除字符串。如果您还想从字符串中间删除字符,请尝试re.sub:

import re
print(re.sub('[\s+]', '', s))

应该打印出来:

astringexample

【讨论】:

  • strip() 接受一个参数来告诉它要跳闸。试试:strip('\t\n\r')
  • 示例结果应该很有帮助:)
  • 最后一个示例与使用str.replace(" ","") 完全相同。您不需要使用re,除非您有多个空格,否则您的示例不起作用。 [] 用于标记单个字符,如果您只使用 \s,则没有必要。使用\s+ 或[\s]+(不必要),但[\s+] 不起作用,特别是如果您想用一个空格替换多个空格,例如将"this example" 变成"this example"。
  • @JorgeE.Cardona - 有一件事你有点不对劲 - \s 将包含标签,而 replace(" ", "") 不会。
【解决方案2】:

在这里看了很多解决方案,理解程度不一,想知道如果字符串是逗号分隔怎么办...

问题

在尝试处理联系信息的 csv 时,我需要解决这个问题:修剪多余的空格和一些垃圾,但保留尾随逗号和内部空格。使用包含联系人注释的字段,我想删除垃圾,留下好东西。修剪掉所有的标点符号和谷壳,我不想丢失复合标记之间的空格,因为我不想稍后重建。

正则表达式和模式:[\s_]+?\W+

该模式使用[\s_]+? 查找任何空白字符和下划线 ('_') 的单个实例,从 1 到无限次数(尽可能少的字符)出现在非单词字符之前1 到无限时间:\W+(相当于[^a-zA-Z0-9_])。具体来说,这会找到大量空白:空字符 (\0)、制表符 (\t)、换行符 (\n)、前馈 (\f)、回车 (\r)。

我认为这样做有两个好处:

  1. 它不会删除您可能想要放在一起的完整单词/标记之间的空格;

  2. Python内置的字符串方法strip()不处理字符串内部,只处理左右两端,默认arg为空字符(见下例:文本中有几个换行符,@987654327 @ 不会在正则表达式模式下将它们全部删除)。 text.strip(' \n\t\r')

这超出了 OP 的问题,但我认为在很多情况下,我们可能会在文本数据中出现奇怪的病态实例,就像我所做的那样(转义字符如何在某些文本中结束)。此外,在类似列表的字符串中,我们不希望删除分隔符,除非分隔符分隔两个空白字符或一些非单词字符,如'-,' 或'-, ,,,'。

注意:不是在谈论 CSV 本身的分隔符。只有 CSV 中数据类似于列表的实例,即 c.s.子字符串的字符串。

完全披露:我只处理文本大约一个月,而正则表达式仅在过去两周内,所以我确信我缺少一些细微差别。也就是说,对于较小的字符串集合(我的是在 12,000 行和 40 奇数列的数据框中),作为通过删除无关字符的最后一步,这非常有效,特别是如果您在其中引入一些额外的空白想要分隔由非单词字符连接的文本,但不想在以前没有空格的地方添加空格。

一个例子:

import re


text = "\"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, , , , \r, , \0, ff dd \n invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, \n i69rpofhfsp9t7c practice 20ignition - 20june \t\n .2134.pdf 2109                                                 \n\n\n\nklkjsdf\""

print(f"Here is the text as formatted:\n{text}\n")
print()
print("Trimming both the whitespaces and the non-word characters that follow them.")
print()
trim_ws_punctn = re.compile(r'[\s_]+?\W+')
clean_text = trim_ws_punctn.sub(' ', text)
print(clean_text)
print()
print("what about 'strip()'?")
print(f"Here is the text, formatted as is:\n{text}\n")
clean_text = text.strip(' \n\t\r')  # strip out whitespace?
print()
print(f"Here is the text, formatted as is:\n{clean_text}\n")

print()
print("Are 'text' and 'clean_text' unchanged?")
print(clean_text == text)

这个输出:

Here is the text as formatted:

"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, ,, , , ff dd 
 invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, 
 i69rpofhfsp9t7c practice 20ignition - 20june 
 .2134.pdf 2109                                                 



klkjsdf" 

using regex to trim both the whitespaces and the non-word characters that follow them.

"portfolio, derp, hello-world, hello-, world, founders, mentors, ffib, biff, 1, 12.18.02, 12, 2013, 9874890288, ff, series a, exit, general mailing, fr, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk,  jim.somedude@blahblah.com, dd invites,subscribed,, master, dd invites,subscribed, ff dd invites, subscribed, alumni spring 2012 deck: https: www.dropbox.com s, i69rpofhfsp9t7c practice 20ignition 20june 2134.pdf 2109 klkjsdf"

Very nice.
What about 'strip()'?

Here is the text, formatted as is:

"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, ,, , , ff dd 
 invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, 
 i69rpofhfsp9t7c practice 20ignition - 20june 
 .2134.pdf 2109                                                 



klkjsdf"


Here is the text, after stipping with 'strip':


"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, ,, , , ff dd 
 invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, 
 i69rpofhfsp9t7c practice 20ignition - 20june 
 .2134.pdf 2109                                                 



klkjsdf"
Are 'text' and 'clean_text' unchanged? 'True'

因此 strip 一次删除一个空格。所以在 OP 的情况下,strip() 很好。但如果事情变得更复杂,正则表达式和类似的模式可能对更一般的设置有一些价值。

see it in action

【讨论】:

    【解决方案3】:
        something = "\t  please_     \t remove_  all_    \n\n\n\nwhitespaces\n\t  "
    
        something = "".join(something.split())
    

    输出:

    please_remove_all_whitespaces


    将 Le Droid 的评论添加到答案中。 用空格隔开:
        something = "\t  please     \t remove  all   extra \n\n\n\nwhitespaces\n\t  "
        something = " ".join(something.split())
    

    输出:

    请删除所有多余的空格

    【讨论】:

    • 简单高效。可以使用 " ".join(... 以空格分隔单词。
    【解决方案4】:

    如果你想在字符串的开头和结尾剪掉空格,你可以这样做:

    some_string = "    Hello,    world!\n    "
    new_string = some_string.strip()
    # new_string is now "Hello,    world!"
    

    这很像 Qt 的 QString::trimmed() 方法,因为它删除了前导和尾随空格,而只保留了内部空格。

    但是,如果您想要 Qt 的 QString::simplified() 方法,它不仅可以删除前导和尾随空格,还可以将所有连续的内部空格“压缩”为一个空格字符,您可以使用 @987654322 的组合@ 和" ".join,像这样:

    some_string = "\t    Hello,  \n\t  world!\n    "
    new_string = " ".join(some_string.split())
    # new_string is now "Hello, world!"
    

    在最后一个示例中,每个内部空格序列都替换为单个空格,同时仍将空格从字符串的开头和结尾修剪掉。

    【讨论】:

      【解决方案5】:

      如果使用 Python 3:在您的打印语句中,以 sep="" 结束。这将分离出所有的空间。

      示例:

      txt="potatoes"
      print("I love ",txt,"",sep="")
      

      这将打印: 我喜欢土豆。

      代替: 我喜欢土豆。

      在你的情况下,因为你会试图搭上 \t,所以 sep="\t"

      【讨论】:

        【解决方案6】:

        (re.sub(' +', ' ',(my_str.replace('\n',' ')))).strip()

        这将删除所有不需要的空格和换行符。希望对您有所帮助

        import re
        my_str = '   a     b \n c   '
        formatted_str = (re.sub(' +', ' ',(my_str.replace('\n',' ')))).strip()
        

        这将导致:

        ' a      b \n c ' 将改为 'a b c'

        【讨论】:

          【解决方案7】:

          对于前导和尾随空格:

          s = '   foo    \t   '
          print s.strip() # prints "foo"
          

          否则,正则表达式有效:

          import re
          pat = re.compile(r'\s+')
          s = '  \t  foo   \t   bar \t  '
          print pat.sub('', s) # prints "foobar"
          

          【讨论】:

          • 你没有编译你的正则表达式。您需要将其设为pat = re.compile(r'\s+')
          • 你一般要sub(" ", s)而不是"",后面会合并单词,你就不能再用.split(" ")来分词了。
          • 很高兴看到print 语句的输出
          【解决方案8】:

          这将删除字符串开头和结尾的所有空格和换行符:

          >>> s = "  \n\t  \n   some \n text \n     "
          >>> re.sub("^\s+|\s+$", "", s)
          >>> "some \n text"
          

          【讨论】:

          • s.strip() 正是这样做的时候为什么要使用正则表达式?
          • s.strip() 仅处理 initial 空格,但在删除其他不需要的字符后不处理“发现”的空格。请注意,这甚至会删除最后一个前导 \n 之后的空格
          • 有人否决了这个答案,但没有解释为什么它有缺陷。为你感到羞耻(@NedBatchelder 如果否决票,请在我解释你的问题时反转,并且你没有提到我的回答实际上破坏的任何内容)
          • Rafe,您可能需要仔细检查:s.strip() 产生的结果与您的正则表达式完全相同。
          • @Rafe,你把它和修剪混淆了。 Strip 执行所需的操作。
          【解决方案9】:

          空白包括空格、制表符和 CRLF。所以我们可以使用一个优雅的one-liner字符串函数是translate。

          ' hello apple'.translate(None, ' \n\t\r')

          或者如果你想彻底

          import string
          ' hello  apple'.translate(None, string.whitespace)
          

          【讨论】:

            【解决方案10】:

            一般情况下,我使用以下方法:

            >>> myStr = "Hi\n Stack Over \r flow!"
            >>> charList = [u"\u005Cn",u"\u005Cr",u"\u005Ct"]
            >>> import re
            >>> for i in charList:
                    myStr = re.sub(i, r"", myStr)
            
            >>> myStr
            'Hi Stack Over  flow'
            

            注意:这仅用于删除“\n”、“\r”和“\t”。它不会删除多余的空格。

            【讨论】:

              【解决方案11】:

              Python trim 方法被调用strip:

              str.strip() #trim
              str.lstrip() #ltrim
              str.rstrip() #rtrim
              

              【讨论】:

              • 这很容易记住,因为 strip 看起来几乎像 trim。
              【解决方案12】:

              尝试翻译

              >>> import string
              >>> print '\t\r\n  hello \r\n world \t\r\n'
              
                hello 
               world  
              >>> tr = string.maketrans(string.whitespace, ' '*len(string.whitespace))
              >>> '\t\r\n  hello \r\n world \t\r\n'.translate(tr)
              '     hello    world    '
              >>> '\t\r\n  hello \r\n world \t\r\n'.translate(tr).replace(' ', '')
              'helloworld'
              

              【讨论】:

                【解决方案13】:

                您还可以使用非常简单的基本函数:str.replace(),适用于空格和制表符:

                >>> whitespaces = "   abcd ef gh ijkl       "
                >>> tabs = "        abcde       fgh        ijkl"
                
                >>> print whitespaces.replace(" ", "")
                abcdefghijkl
                >>> print tabs.replace(" ", "")
                abcdefghijkl
                

                简单易行。

                【讨论】:

                • 但是,唉,这也删除了内部空间,而原始问题中的示例未触及内部空间。
                【解决方案14】:

                还没有人发布这些正则表达式解决方案。

                匹配:

                >>> import re
                >>> p=re.compile('\\s*(.*\\S)?\\s*')
                
                >>> m=p.match('  \t blah ')
                >>> m.group(1)
                'blah'
                
                >>> m=p.match('  \tbl ah  \t ')
                >>> m.group(1)
                'bl ah'
                
                >>> m=p.match('  \t  ')
                >>> print m.group(1)
                None
                

                搜索(您必须以不同方式处理“仅空格”输入案例):

                >>> p1=re.compile('\\S.*\\S')
                
                >>> m=p1.search('  \tblah  \t ')
                >>> m.group()
                'blah'
                
                >>> m=p1.search('  \tbl ah  \t ')
                >>> m.group()
                'bl ah'
                
                >>> m=p1.search('  \t  ')
                >>> m.group()
                Traceback (most recent call last):
                File "<stdin>", line 1, in <module>
                AttributeError: 'NoneType' object has no attribute 'group'
                

                如果您使用re.sub,您可能会删除内部空格,这可能是不受欢迎的。

                【讨论】:

                  【解决方案15】:
                  #how to trim a multi line string or a file
                  
                  s=""" line one
                  \tline two\t
                  line three """
                  
                  #line1 starts with a space, #2 starts and ends with a tab, #3 ends with a space.
                  
                  s1=s.splitlines()
                  print s1
                  [' line one', '\tline two\t', 'line three ']
                  
                  print [i.strip() for i in s1]
                  ['line one', 'line two', 'line three']
                  
                  
                  
                  
                  #more details:
                  
                  #we could also have used a forloop from the begining:
                  for line in s.splitlines():
                      line=line.strip()
                      process(line)
                  
                  #we could also be reading a file line by line.. e.g. my_file=open(filename), or with open(filename) as myfile:
                  for line in my_file:
                      line=line.strip()
                      process(line)
                  
                  #moot point: note splitlines() removed the newline characters, we can keep them by passing True:
                  #although split() will then remove them anyway..
                  s2=s.splitlines(True)
                  print s2
                  [' line one\n', '\tline two\t\n', 'line three ']
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2018-08-26
                    • 2017-03-16
                    • 1970-01-01
                    • 2012-08-07
                    • 2013-10-21
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-05-07
                    相关资源
                    最近更新 更多