【问题标题】:Remove all special characters, punctuation and spaces from string从字符串中删除所有特殊字符、标点符号和空格
【发布时间】:2011-08-16 03:45:50
【问题描述】:

我需要从字符串中删除所有特殊字符、标点符号和空格,以便我只有字母和数字。

【问题讨论】:

    标签: python regex string


    【解决方案1】:

    10 年后,我在下面写了最好的解决方案。 您可以从字符串中删除/清除所有特殊字符、标点符号、ASCII 字符和空格。

    from clean_text import clean
    
    string = 'Special $#! characters   spaces 888323'
    new = clean(string,lower=False,no_currency_symbols=True, no_punct = True,replace_with_currency_symbol='')
    print(new)
    Output ==> 'Special characters spaces 888323'
    you can replace space if you want.
    update = new.replace(' ','')
    print(update)
    Output ==> 'Specialcharactersspaces888323'
    

    【讨论】:

      【解决方案2】:

      TLDR

      我为提供的答案计时。

      import re
      re.sub('\W+','', string)
      

      通常比第二快提供的最佳答案快 3 倍

      使用此选项时应小心。使用此方法可能无法对某些特殊字符(例如 ø)进行条带化。


      看到这一点后,我有兴趣通过找出哪些执行时间最短来扩展提供的答案,因此我通过timeit 对照两个示例字符串检查了一些建议的答案:

      • string1 = 'Special $#! characters spaces 888323'
      • string2 = 'how much for the maple syrup? $20.99? That s ridiculous!!!'

      示例 1

      '.join(e for e in string if e.isalnum())
      
      • string1 - 结果:10.7061979771
      • string2 - 结果:7.78372597694

      示例 2

      import re
      re.sub('[^A-Za-z0-9]+', '', string)
      
      • string1 - 结果:7.10785102844
      • string2 - 结果:4.12814903259

      示例 3

      import re
      re.sub('\W+','', string)
      
      • string1 - 结果:3.11899876595
      • string2 - 结果:2.78014397621

      以上结果是平均返回结果最低的乘积:repeat(3, 2000000)

      示例 3 可以比 示例 1 快 3 倍。

      【讨论】:

      • @kkurian 如果您阅读了我的回答的开头,这仅仅是对上述先前提出的解决方案的比较。您可能想对原始答案发表评论...stackoverflow.com/a/25183802/2560922
      • 哦,我知道你打算用这个去哪里了。完成!
      • 在处理大型语料库时必须考虑示例 3。
      • 有效!感谢您的关注。
      • 你能比较一下我的答案''.join([*filter(str.isalnum, string)])
      【解决方案3】:

      这将从字符串中删除所有特殊字符、标点符号和空格,并且只包含数字和字母。

      import re
      
      sample_str = "Hel&&lo %% Wo$#rl@d"
      
      # using isalnum()
      print("".join(k for k in sample_str if k.isalnum()))
      
      
      # using regex
      op2 = re.sub("[^A-Za-z]", "", sample_str)
      print(f"op2 = ", op2)
      
      
      special_char_list = ["$", "@", "#", "&", "%"]
      
      # using list comprehension
      op1 = "".join([k for k in sample_str if k not in special_char_list])
      print(f"op1 = ", op1)
      
      
      # using lambda function
      op3 = "".join(filter(lambda x: x not in special_char_list, sample_str))
      print(f"op3 = ", op3)
      

      【讨论】:

        【解决方案4】:

        这将删除除空格以外的所有非字母数字字符。

        string = "Special $#! characters   spaces 888323"
        ''.join(e for e in string if (e.isalnum() or e.isspace()))
        

        特殊字符空格 888323

        【讨论】:

          【解决方案5】:

          对于其他语言,如德语、西班牙语、丹麦语、法语等包含特殊字符(如德语“Umlaute”为üäö),只需将这些添加到正则表达式搜索字符串:

          德语示例:

          re.sub('[^A-ZÜÖÄa-z0-9]+', '', mystring)
          

          【讨论】:

            【解决方案6】:

            string.punctuation 包含以下字符:

            '!"#$%&\'()*+,-./:;?@[\]^_`{|}~'

            您可以使用 translate 和 maketrans 函数将标点符号映射到空值(替换)

            import string
            
            'This, is. A test!'.translate(str.maketrans('', '', string.punctuation))
            

            输出:

            'This is A test'
            

            【讨论】:

              【解决方案7】:

              这是一个匹配非字母或数字的字符串的正则表达式:

              [^A-Za-z0-9]+
              

              这是执行正则表达式替换的 Python 命令:

              re.sub('[^A-Za-z0-9]+', '', mystring)
              

              【讨论】:

              • 亲吻:保持简单愚蠢!这比非正则表达式解决方案更短且更易于阅读,并且也可能更快。 (不过,我会添加一个+ 量词来稍微提高它的效率。)
              • 这也会删除单词之间的空格,“great place” -> “greatplace”。如何避免?
              • @Reihan_amn 只需在正则表达式中添加一个空格,就变成:[^A-Za-z0-9 ]+
              • 我猜这不适用于其他语言中的修改字符,例如 áöñ、等等。我说得对吗?如果是这样,它的正则表达式如何?
              • 这不适用于西班牙语、德语、丹麦语和其他语言。
              【解决方案8】:

              这可以在没有正则表达式的情况下完成:

              >>> string = "Special $#! characters   spaces 888323"
              >>> ''.join(e for e in string if e.isalnum())
              'Specialcharactersspaces888323'
              

              你可以使用str.isalnum:

              S.isalnum() -> bool
              
              Return True if all characters in S are alphanumeric
              and there is at least one character in S, False otherwise.
              

              如果您坚持使用正则表达式,其他解决方案也可以。但是请注意,如果它可以在不使用正则表达式的情况下完成,那是最好的方法。

              【讨论】:

              • 不使用正则表达式作为经验法则的原因是什么?
              • @ChrisDutrow 正则表达式比 python 字符串内置函数慢
              • @DiegoNavarro 但事实并非如此,我对isalnum() 和正则表达式版本都进行了基准测试,而正则表达式版本的速度提高了 50-75%
              • 在 Python3 中试过这个 - 它接受 unicode 字符,所以对我来说没用。以 string = "B223323\§§§$3\u445454" 为例。结果? 'B2233233䑔54'
              • 另外:“对于 8 位字符串,此方法取决于区域设置。”!因此,正则表达式替代方案更好!
              【解决方案9】:

              Python 2.*

              我认为 filter(str.isalnum, string) 有效

              In [20]: filter(str.isalnum, 'string with special chars like !,#$% etcs.')
              Out[20]: 'stringwithspecialcharslikeetcs'
              

              Python 3.*

              在 Python3 中,filter( ) 函数将返回一个可迭代对象(而不是与上面不同的字符串)。必须重新加入才能从 itertable 中获取字符串:

              ''.join(filter(str.isalnum, string)) 
              

              或者通过list加入使用(not sure but can be fast a bit

              ''.join([*filter(str.isalnum, string)])
              

              注意:在[*args] 中解包从Python >= 3.5 有效

              【讨论】:

              • @Alexey 正确,在 python3 中,mapfilterreduce 返回可迭代对象。仍然在 Python3+ 中,我更喜欢''.join(filter(str.isalnum, string))(或在加入时传递列表使用''.join([*filter(str.isalnum, string)]))而不是接受的答案。
              • 我不确定''.join(filter(str.isalnum, string)) 是对filter(str.isalnum, string) 的改进,至少可以阅读。这真的是 Pythreenic(是的,你可以使用那个)的方式来做到这一点吗?
              • @TheProletariat 重点是只是filter(str.isalnum, string) 不要在Python3 中返回字符串,因为Python-3 中的filter( ) 返回迭代器而不是参数类型,这与Python-2 不同。+
              • @GrijeshChauhan,我认为您应该更新您的答案以包含您的 Python2 和 Python3 建议。
              【解决方案10】:

              与使用正则表达式的其他人不同,我会尝试排除所有不是我想要的字符,而不是明确列举我不想要的。

              例如,如果我只想要从“a 到 z”(大写和小写)和数字的字符,我会排除其他所有字符:

              import re
              s = re.sub(r"[^a-zA-Z0-9]","",s)
              

              这意味着“用一个空字符串替换每个不是数字的字符,或者'a to z'或'A to Z'范围内的字符”。

              事实上,如果你在你的正则表达式的第一个位置插入特殊字符^,你会得到否定。

              额外提示:如果您还需要小写结果,则可以使正则表达式更快更容易,只要您现在找不到任何大写即可。

              import re
              s = re.sub(r"[^a-z0-9]","",s.lower())
              

              【讨论】:

                【解决方案11】:
                import re
                my_string = """Strings are amongst the most popular data types in Python. We can create the strings by enclosing characters in quotes. Python treats single quotes the 
                

                同双引号。"""

                # if we need to count the word python that ends with or without ',' or '.' at end
                
                count = 0
                for i in text:
                    if i.endswith("."):
                        text[count] = re.sub("^([a-z]+)(.)?$", r"\1", i)
                    count += 1
                print("The count of Python : ", text.count("python"))
                

                【讨论】:

                  【解决方案12】:
                  s = re.sub(r"[-()\"#/@;:<>{}`+=~|.!?,]", "", s)
                  

                  【讨论】:

                    【解决方案13】:

                    使用翻译:

                    import string
                    
                    def clean(instr):
                        return instr.translate(None, string.punctuation + ' ')
                    

                    警告:仅适用于 ascii 字符串。

                    【讨论】:

                    • 版本差异?我用 py3.4 得到TypeError: translate() takes exactly one argument (2 given)
                    • 它只适用于 Python2.7。请参阅below 答案以将translate 与 Python3 一起使用。
                    【解决方案14】:
                    import re
                    abc = "askhnl#$%askdjalsdk"
                    ddd = abc.replace("#$%","")
                    print (ddd)
                    

                    你会看到你的结果

                    'askhnlaskdjalsdk

                    【讨论】:

                    • 等待....您导入了 re 但从未使用过它。您的 replace 标准仅适用于该特定字符串。如果你的字符串是abc = "askhnl#$%!askdjalsdk" 怎么办?我认为除了#$% 模式之外不会有任何作用。可能想要调整它
                    【解决方案15】:

                    更短的方式:

                    import re
                    cleanString = re.sub('\W+','', string )
                    

                    如果您希望单词和数字之间有空格,请将 '' 替换为 ' '

                    【讨论】:

                    • 除了 _ 在 \w 中并且是此问题上下文中的特殊字符。
                    • 取决于上下文 - 下划线对于文件名和其他标识符非常有用,以至于我不将其视为特殊字符而是将其视为已清理的空间。我自己通常使用此方法。
                    • r'\W+' - 稍微偏离主题(而且非常迂腐),但我建议所有正则表达式模式都是raw strings
                    • 此过程不将下划线(_)视为特殊字符。
                    • 删除_ 的简单更改:r"[^A-Za-z]+" 而不是r"\W+"
                    【解决方案16】:
                    #!/usr/bin/python
                    import re
                    
                    strs = "how much for the maple syrup? $20.99? That's ricidulous!!!"
                    print strs
                    nstr = re.sub(r'[?|$|.|!]',r'',strs)
                    print nstr
                    nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)
                    print nestr
                    

                    您可以添加更多特殊字符,将被替换为 '' 没有任何意义,即它们将被删除。

                    【讨论】:

                      【解决方案17】:

                      最通用的方法是使用对每个字符进行分类的 unicodedata 表的“类别”。例如。以下代码仅根据类别过滤可打印字符:

                      import unicodedata
                      # strip of crap characters (based on the Unicode database
                      # categorization:
                      # http://www.sql-und-xml.de/unicode-database/#kategorien
                      
                      PRINTABLE = set(('Lu', 'Ll', 'Nd', 'Zs'))
                      
                      def filter_non_printable(s):
                          result = []
                          ws_last = False
                          for c in s:
                              c = unicodedata.category(c) in PRINTABLE and c or u'#'
                              result.append(c)
                          return u''.join(result).replace(u'#', u' ')
                      

                      查看上面给出的所有相关类别的 URL。你当然也可以过滤 按标点符号分类。

                      【讨论】:

                      • 每行末尾的$ 是什么意思?
                      • 如果是复制和粘贴问题,你应该修复它吗?
                      【解决方案18】:

                      假设您想要使用正则表达式并且您想要/需要 2to3-ready 的 Unicode 认知 2.x 代码:

                      >>> import re
                      >>> rx = re.compile(u'[\W_]+', re.UNICODE)
                      >>> data = u''.join(unichr(i) for i in range(256))
                      >>> rx.sub(u'', data)
                      u'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\xaa\xb2 [snip] \xfe\xff'
                      >>>
                      

                      【讨论】:

                        猜你喜欢
                        • 2017-12-28
                        • 2021-10-16
                        • 2014-08-17
                        • 2021-04-23
                        • 2016-02-20
                        • 2014-02-22
                        • 2016-12-21
                        • 2015-01-13
                        • 2011-09-27
                        相关资源
                        最近更新 更多