Supprimer tous les caractères spéciaux, la ponctuation et les espaces de la chaîne

236

Je dois supprimer tous les caractères spéciaux, la ponctuation et les espaces d'une chaîne afin de n'avoir que des lettres et des chiffres.

user664546
la source

Réponses:

351

Cela peut être fait sans regex:

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

Vous pouvez utiliser 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.

Si vous insistez sur l'utilisation de regex, d'autres solutions feront l'affaire. Notez cependant que si cela peut être fait sans utiliser une expression régulière, c'est la meilleure façon de procéder.

user225312
la source
7
Quelle est la raison de ne pas utiliser l'expression régulière comme règle empirique?
Chris Dutrow
@ChrisDutrow regex sont plus lentes que les fonctions intégrées de chaîne python
Diego Navarro
Cela ne fonctionne que lorsque la chaîne est en unicode . Sinon, il se plaint comme si l'objet 'str' n'avait pas d'attribut 'isalnum' 'isnumeric' et ainsi de suite.
NeoJi
10
@DiegoNavarro sauf que ce n'est pas vrai, j'ai comparé les isalnum()versions regex et regex, et celle regex est 50-75% plus rapide
Francisco Couzo
2
En outre: "Pour les chaînes 8 bits, cette méthode dépend des paramètres régionaux."! Ainsi, l'alternative regex est strictement meilleure!
Antti Haapala
232

Voici une expression régulière pour faire correspondre une chaîne de caractères qui ne sont pas des lettres ou des chiffres:

[^A-Za-z0-9]+

Voici la commande Python pour effectuer une substitution regex:

re.sub('[^A-Za-z0-9]+', '', mystring)
Andy White
la source
10
KISS: Keep It Simple Stupid! C'est plus court et beaucoup plus facile à lire que les solutions non regex et peut aussi être plus rapide. (Cependant, j'ajouterais un +quantificateur pour améliorer un peu son efficacité.)
ridgerunner
1
cela supprime également les espaces entre les mots, "grand endroit" -> "grand endroit". Comment l'éviter?
Reihan_amn
5
@Reihan_amn Ajoutez simplement un espace au regex, pour qu'il devienne:[^A-Za-z0-9 ]+
ostroon
1
@ andy-white pouvez-vous s'il vous plaît ajouter l'espace au regex dans la réponse? L'espace n'est pas un caractère spécial ...
Ufos
3
Je suppose que cela ne fonctionne pas avec un caractère modifié dans d'autres langues, comme á , ö , ñ , etc. Ai-je raison? Si oui, comment serait-ce l'expression rationnelle?
HuLu ViCa
50

Manière plus courte:

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

Si vous voulez des espaces entre les mots et les nombres, remplacez '' par ''

tuxErrante
la source
3
Sauf que _ est dans \ w et est un caractère spécial dans le contexte de cette question.
kkurian
Dépend du contexte - le soulignement est très utile pour les noms de fichiers et autres identifiants, au point que je ne le traite pas comme un caractère spécial mais plutôt comme un espace aseptisé. J'utilise généralement cette méthode moi-même.
Echelon
1
r'\W+'- légèrement hors sujet (et très pédant) mais je suggère une habitude que tous les motifs d'expression régulière soient des chaînes brutes
Bob Stein
2
Cette procédure ne traite pas le trait de soulignement (_) comme un caractère spécial.
Md. Sabbir Ahmed
30

Après avoir vu cela, j'étais intéressé à développer les réponses fournies en découvrant ce qui s'exécute dans le moins de temps, donc j'ai parcouru et vérifié certaines des réponses proposées avec timeitdeux des chaînes d'exemple:

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

Exemple 1

'.join(e for e in string if e.isalnum())

  • string1 - Résultat: 10.7061979771
  • string2 - Résultat: 7.78372597694

Exemple 2

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

  • string1 - Résultat: 7.10785102844
  • string2 - Résultat: 4.12814903259

Exemple 3

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

  • string1 - Résultat: 3.11899876595
  • string2 - Résultat: 2.78014397621

Les résultats ci-dessus sont le produit du résultat retourné le plus bas d'une moyenne de: repeat(3, 2000000)

L'exemple 3 peut être 3 fois plus rapide que l' exemple 1 .

mbeacom
la source
@kkurian Si vous lisez le début de ma réponse, ce n'est qu'une comparaison des solutions précédemment proposées ci-dessus. Vous voudrez peut-être commenter la réponse d'origine ... stackoverflow.com/a/25183802/2560922
mbeacom
Oh, je vois où tu vas avec ça. Terminé!
kkurian
1
Doit considérer l'exemple 3, lorsqu'il s'agit d'un grand corpus.
HARSH NILESH PATHAK
Valide! Merci de l'avoir noté.
mbeacom
pouvez-vous comparer ma réponse''.join([*filter(str.isalnum, string)])
Grijesh Chauhan
22

Python 2. *

Je pense que ça filter(str.isalnum, string)marche

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

Python 3. *

En Python3, la filter( )fonction retournerait un objet itérable (au lieu d'une chaîne contrairement à ce qui précède). Il faut se joindre à nouveau pour obtenir une chaîne d'itertable:

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

ou pour passer listen jointure ( pas sûr mais peut être un peu rapide )

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

note: décompresser en [*args]valide depuis Python> = 3.5

Grijesh Chauhan
la source
4
@Alexey corriger, dans python3 map, filteret reduce retourne un objet au lieu itertable. Toujours en Python3 +, je préférerai ''.join(filter(str.isalnum, string)) (ou passer la liste en utilisation conjointe ''.join([*filter(str.isalnum, string)])) à la réponse acceptée.
Grijesh Chauhan
Je ne suis pas certain que ce ''.join(filter(str.isalnum, string))soit une amélioration filter(str.isalnum, string), du moins à lire. Est-ce vraiment la façon Pythreenic (ouais, vous pouvez l'utiliser) de le faire?
TheProletariat
1
@TheProletariat Le point est simplement defilter(str.isalnum, string) ne pas renvoyer de chaîne en Python3 car filter( )en Python-3 renvoie l'itérateur plutôt que le type d'argument contrairement à Python-2. +
Grijesh Chauhan
@GrijeshChauhan, je pense que vous devriez mettre à jour votre réponse pour inclure à la fois vos recommandations Python2 et Python3.
mwfearnley
18
#!/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

vous pouvez ajouter plus de caractère spécial et qui sera remplacé par '' signifie rien, c'est-à-dire qu'ils seront supprimés.

pkm
la source
16

Contrairement à tout le monde en utilisant regex, j'essayerais d'exclure chaque caractère qui n'est pas ce que je veux, au lieu d'énumérer explicitement ce que je ne veux pas.

Par exemple, si je veux uniquement des caractères de 'a à z' (majuscules et minuscules) et des chiffres, j'exclure tout le reste:

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

Cela signifie "remplacer chaque caractère qui n'est pas un nombre ou un caractère de la plage" a à z "ou" A à Z "par une chaîne vide".

En fait, si vous insérez le caractère spécial ^à la première place de votre expression régulière, vous obtiendrez la négation.

Astuce supplémentaire: si vous devez également minuscule le résultat, vous pouvez rendre l'expression régulière encore plus rapide et plus facile, tant que vous ne trouverez pas de majuscules maintenant.

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

En supposant que vous souhaitez utiliser une expression régulière et que vous souhaitez / ayez besoin d'un code 2.x compatible Unicode prêt pour le 2to3:

>>> 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'
>>>
John Machin
la source
7
s = re.sub(r"[-()\"#/@;:<>{}`+=~|.!?,]", "", s)
sneha
la source
6

L'approche la plus générique utilise les «catégories» de la table unicodedata qui classe chaque caractère. Par exemple, le code suivant filtre uniquement les caractères imprimables en fonction de leur catégorie:

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' ')

Regardez l'URL ci-dessus pour toutes les catégories connexes. Vous pouvez également bien sûr filtrer par catégories de ponctuation.

Andreas Jung
la source
Qu'y a-t-il $à la fin de chaque ligne?
John Machin
Si c'est un problème de copier-coller, devriez-vous le résoudre?
Olli
5

string.punctuation contient les caractères suivants:

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

Vous pouvez utiliser les fonctions translate et maketrans pour mapper les ponctuations aux valeurs vides (remplacer)

import string

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

Production:

'This is A test'
Vlad Bezden
la source
4

Utiliser traduire:

import string

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

Avertissement: ne fonctionne que sur les chaînes ascii.

jjmurre
la source
Différence de version? Je reçois TypeError: translate() takes exactly one argument (2 given)avec py3.4
matt wilkie
1
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 

Identique aux guillemets doubles. "" "

# 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"))
Vinay Kumar Kuresi
la source
0
import re
abc = "askhnl#$%askdjalsdk"
ddd = abc.replace("#$%","")
print (ddd)

et vous verrez votre résultat comme

«askhnlaskdjalsdk

Dsw Wds
la source
4
attendez .... vous l'avez importé remais ne l' avez jamais utilisé. Vos replacecritères ne fonctionnent que pour cette chaîne spécifique. Et si votre chaîne l'est abc = "askhnl#$%!askdjalsdk"? Je ne pense pas que cela fonctionnera sur autre chose que le #$%motif. Je
pourrais
0

Suppression des ponctuations, des nombres et des caractères spéciaux

Exemple :-

entrez la description de l'image ici

Code

combi['tidy_tweet'] = combi['tidy_tweet'].str.replace("[^a-zA-Z#]", " ") 

Résultat:- entrez la description de l'image ici

Merci :)

Harish Kumawat
la source
0

Pour les autres langues comme l' allemand, l' espagnol, danois, français , etc qui contiennent des caractères spéciaux (comme « Umlaute » allemand ü, ä, ö) il suffit d' ajouter ceux - ci à la chaîne de recherche regex:

Exemple pour l'allemand:

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