Usuń wszystkie znaki specjalne, znaki interpunkcyjne i spacje z łańcucha


Odpowiedzi:


351

Można to zrobić bez wyrażenia regularnego:

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

Możesz użyć 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.

Jeśli nalegasz na użycie wyrażenia regularnego, inne rozwiązania sprawdzą się. Należy jednak pamiętać, że jeśli można tego dokonać bez użycia wyrażenia regularnego, jest to najlepszy sposób, aby to zrobić.


7
Jaki jest powód, dla którego reguła nie jest wyrażeniem regularnym?
Chris Dutrow

Wyrażenie regularne @ChrisDutrow jest wolniejsze niż wbudowane funkcje łańcucha python
Diego Navarro,

Działa to tylko wtedy, gdy ciąg znaków jest w Unicode . W przeciwnym razie narzeka, że ​​obiekt „str” nie ma atrybutu „isalnum” „isnumeric” i tak dalej.
NeoJi

10
@DiegoNavarro oprócz tego, że to nieprawda, porównałem obie isalnum()wersje i wyrażenia regularne, a jeden z
wyrażeń

2
Dodatkowo: „W przypadku ciągów 8-bitowych ta metoda zależy od ustawień regionalnych.”! Zatem alternatywa wyrażeń regularnych jest zdecydowanie lepsza!
Antti Haapala

232

Oto wyrażenie pasujące do ciągu znaków, które nie są literami ani cyframi:

[^A-Za-z0-9]+

Oto polecenie Pythona, aby wykonać podstawienie wyrażenia regularnego:

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

10
KISS: Keep Simple Simple Głupi! Jest to krótsze i znacznie łatwiejsze do odczytania niż rozwiązania inne niż wyrażenia regularne, a także może być szybsze. (Dodałbym jednak +kwantyfikator, aby nieco poprawić jego wydajność.)
ridgerunner

1
usuwa to również spacje między słowami „świetne miejsce” -> „świetne miejsce”. Jak tego uniknąć?
Reihan_amn

5
@Reihan_amn Wystarczy dodać spację do wyrażenia regularnego, aby stała się:[^A-Za-z0-9 ]+
ostroon

1
@ andy-white, czy możesz dodać spację do wyrażenia regularnego w odpowiedzi? Spacja nie jest postacią specjalną ...
Ufos

3
Myślę, że to nie działa ze zmodyfikowanymi znakami w innych językach, takich jak á , ö , ñ itp. Czy mam rację? Jeśli tak, to jak by to wyglądało?
HuLu ViCa

50

Krótsza droga:

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

Jeśli chcesz, aby spacje między słowami i cyframi zastąpiły słowa „”


3
Tyle że _ jest w \ w i jest znakiem specjalnym w kontekście tego pytania.
kkurian

Zależy od kontekstu - podkreślenie jest bardzo przydatne w nazwach plików i innych identyfikatorach, do tego stopnia, że ​​nie traktuję go jako znaku specjalnego, ale raczej zdezynfekowanej przestrzeni. Z reguły tej metody używam sam.
Echelon

1
r'\W+'- nieco nie na temat (i bardzo pedantyczny), ale sugeruję nawyk, aby wszystkie wzorce wyrażeń regularnych były surowymi łańcuchami
Bob Stein

2
Ta procedura nie traktuje podkreślenia (_) jako znaku specjalnego.
Md. Sabbir Ahmed

30

Po tym, zainteresowałem się rozszerzeniem podanych odpowiedzi, dowiedzieć się, które polecenie wykonuje się w jak najkrótszym czasie, więc przejrzałem i sprawdziłem niektóre z proponowanych odpowiedzi pod kątem timeitdwóch przykładowych ciągów:

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

Przykład 1

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

  • string1 - Wynik: 10,7061979771
  • string2 - Wynik: 7,78372597694

Przykład 2

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

  • string1 - Wynik: 7,17785102844
  • string2 - Wynik: 4,12814903259

Przykład 3

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

  • string1 - Wynik: 3,11899876595
  • string2 - Wynik: 2,78014397621

Powyższe wyniki są wynikiem najniższego zwracanego wyniku ze średniej: repeat(3, 2000000)

Przykład 3 może być 3 razy szybszy niż w przykładzie 1 .


@kkurian Jeśli czytasz początek mojej odpowiedzi, jest to jedynie porównanie wcześniej zaproponowanych rozwiązań powyżej. Być może zechcesz skomentować pierwotną odpowiedź ... stackoverflow.com/a/25183802/2560922
mbeacom

Och, rozumiem, gdzie idziesz z tym. Gotowe!
kkurian

1
W przypadku dużego korpusu należy wziąć pod uwagę przykład 3.
HARSH NILESH PATHAK

Ważny! Dziękuję za uwagę.
mbeacom

czy możesz porównać moją odpowiedź''.join([*filter(str.isalnum, string)])
Grijesh Chauhan

22

Python 2. *

Myślę, że po prostu filter(str.isalnum, string)działa

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

Python 3. *

W Python3 filter( )funkcja zwróci obiekt itertowalny (zamiast ciągu w przeciwieństwie do powyższego). Trzeba połączyć się z powrotem, aby uzyskać ciąg z itertable:

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

lub przekazać listdołączenie do użycia ( nie jestem pewien, ale może być trochę szybki )

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

Uwaga: rozpakowywanie jest [*args]ważne z Pythona> = 3.5


4
@Alexey poprawić, W python3 map, filteri reduce powraca itertable Object zamiast. Nadal w Python3 + wolę ''.join(filter(str.isalnum, string)) (lub przekazać listę przy łączeniu ''.join([*filter(str.isalnum, string)])) niż zaakceptowaną odpowiedź.
Grijesh Chauhan

Nie jestem pewien, ''.join(filter(str.isalnum, string))czy poprawa filter(str.isalnum, string), przynajmniej do czytania. Czy to naprawdę jest Pythreenic (tak, możesz tego użyć), aby to zrobić?
TheProletariat

1
@TheProletariat Chodzi o to, po prostufilter(str.isalnum, string) nie zwracają ciąg w Python3 jak filter( )w Python3 zwraca iterator zamiast typu argumentu przeciwieństwie python-2 +.
Grijesh Chauhan

@GrijeshChauhan, myślę, że powinieneś zaktualizować swoją odpowiedź, aby zawierała zarówno rekomendacje Python2, jak i 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

możesz dodać więcej znaków specjalnych, które zostaną zastąpione przez „” oznacza nic, tzn. zostaną usunięte.


16

W odróżnieniu od innych osób używających wyrażenia regularnego, starałbym się wykluczyć każdą postać, która nie jest tym, czego chcę, zamiast wyraźnego wyliczenia tego, czego nie chcę.

Na przykład, jeśli chcę tylko znaki od „a do z” (wielkie i małe litery) oraz cyfry, wykluczę wszystko inne:

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

Oznacza to „zamień pusty znak na każdy znak, który nie jest liczbą, lub znak z zakresu od„ a do z ”lub„ A do Z ”.

W rzeczywistości, jeśli wstawisz znak specjalny ^na pierwszym miejscu wyrażenia regularnego, otrzymasz negację.

Dodatkowa wskazówka: jeśli musisz również pomniejszyć wynik, możesz sprawić, że wyrażenie regularne będzie jeszcze szybsze i łatwiejsze, o ile nie znajdziesz teraz wielkich liter.

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

9

Zakładając, że chcesz użyć wyrażenia regularnego i potrzebujesz / potrzebujesz kodu rozpoznającego Unicode 2.x, który jest gotowy na 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'
>>>


6

Najbardziej ogólnym podejściem jest użycie „kategorii” tabeli unicodedata, która klasyfikuje każdy pojedynczy znak. Np. Poniższy kod filtruje tylko znaki drukowalne na podstawie ich kategorii:

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

Spójrz na podany powyżej adres URL dla wszystkich powiązanych kategorii. Możesz także oczywiście filtrować według kategorii interpunkcyjnych.


O co chodzi $na końcu każdej linii?
John Machin

Jeśli to problem z kopiowaniem i wklejaniem, czy to należy naprawić?
Olli

5

string.punctuation zawiera następujące znaki:

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

Możesz użyć funkcji translacji i maketrans do mapowania interpunkcji na puste wartości (zamień)

import string

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

Wynik:

'This is A test'

4

Użyj tłumacza:

import string

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

Uwaga: Działa tylko na ciągach ascii.


Różnica wersji? Dostaję TypeError: translate() takes exactly one argument (2 given)z 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 

to samo co podwójne cudzysłowy. ”„ ”

# 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"))

0
import re
abc = "askhnl#$%askdjalsdk"
ddd = abc.replace("#$%","")
print (ddd)

i zobaczysz swój wynik jako

„askhnlaskdjalsdk


4
czekaj .... zaimportowałeś, reale nigdy go nie użyłeś. Twoje replacekryteria działają tylko dla tego określonego ciągu. Co jeśli twój ciąg jest abc = "askhnl#$%!askdjalsdk"? Nie sądzę, że zadziała na czymkolwiek innym niż #$%wzór. Może chcę to poprawić
JChao

0

Usuwanie interpunkcji, cyfr i znaków specjalnych

Przykład: -

wprowadź opis zdjęcia tutaj

Kod

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

Wynik:- wprowadź opis zdjęcia tutaj

Dzięki :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.