Hapus semua karakter khusus, tanda baca, dan spasi dari string

236

Saya perlu menghapus semua karakter khusus, tanda baca dan spasi dari string sehingga saya hanya memiliki huruf dan angka.

pengguna664546
sumber

Jawaban:

351

Ini dapat dilakukan tanpa regex:

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

Anda bisa menggunakan 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.

Jika Anda bersikeras menggunakan regex, solusi lain akan baik-baik saja. Namun perhatikan bahwa jika itu dapat dilakukan tanpa menggunakan ekspresi reguler, itulah cara terbaik untuk melakukannya.

pengguna225312
sumber
7
Apa alasannya tidak menggunakan regex sebagai aturan praktis?
Chris Dutrow
@ChrisDutrow regex lebih lambat dari fungsi bawaan string python
Diego Navarro
Ini hanya berfungsi ketika string berada di unicode . Kalau tidak, ia mengeluh seperti 'str' objek tidak memiliki atribut 'isalnum' 'isnumeric' dan seterusnya.
NeoJi
10
@DiegoNavarro, kecuali itu tidak benar, saya membuat benchmark versi isalnum()dan regex, dan regex 50-75% lebih cepat
Francisco Couzo
2
Selain itu: "Untuk string 8-bit, metode ini bergantung pada lokal."! Jadi alternatif regex benar-benar lebih baik!
Antti Haapala
232

Berikut adalah regex yang cocok dengan serangkaian karakter yang bukan huruf atau angka:

[^A-Za-z0-9]+

Berikut adalah perintah Python untuk melakukan substitusi regex:

re.sub('[^A-Za-z0-9]+', '', mystring)
Andy White
sumber
10
KISS: Keep It Simple Stupid! Ini lebih pendek dan lebih mudah dibaca daripada solusi non-regex dan mungkin lebih cepat juga. (Namun, saya akan menambahkan +quantifier untuk sedikit meningkatkan efisiensinya.)
ridgerunner
1
ini juga menghilangkan spasi di antara kata-kata, "tempat yang bagus" -> "tempat yang hebat". Bagaimana cara menghindarinya?
Reihan_amn
5
@Reihan_amn Cukup tambahkan spasi ke regex, jadi itu menjadi:[^A-Za-z0-9 ]+
ostroon
1
@ andy-white bisakah Anda menambahkan spasi pada regex di jawabannya? Ruang bukan karakter khusus ...
Ufos
3
Saya kira ini tidak berfungsi dengan karakter yang dimodifikasi dalam bahasa lain, seperti á , ö , ñ , dll. Apakah saya benar? Jika demikian, bagaimana regexnya?
HuLu ViCa
50

Cara yang lebih pendek:

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

Jika Anda ingin spasi antara kata dan angka gantikan '' dengan ''

tuxErrante
sumber
3
Kecuali bahwa _ ada di \ w dan merupakan karakter khusus dalam konteks pertanyaan ini.
kkurian
Bergantung pada konteksnya - garis bawah sangat berguna untuk nama file dan pengidentifikasi lainnya, sampai-sampai saya tidak memperlakukannya sebagai karakter khusus melainkan ruang yang disanitasi. Saya biasanya menggunakan metode ini sendiri.
Eselon
1
r'\W+'- agak off topic (dan sangat pedantic) tapi saya menyarankan kebiasaan bahwa semua pola regex menjadi string mentah
Bob Stein
2
Prosedur ini tidak memperlakukan garis bawah (_) sebagai karakter khusus.
Md. Sabbir Ahmed
30

Setelah melihat ini, saya tertarik untuk memperluas jawaban yang disediakan dengan mencari tahu yang dieksekusi dalam waktu paling sedikit, jadi saya memeriksa dan memeriksa beberapa jawaban yang diajukan dengan timeitdua contoh string:

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

Contoh 1

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

  • string1 - Hasil: 10.7061979771
  • string2 - Hasil: 7.78372597694

Contoh 2

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

  • string1 - Hasil: 7.10785102844
  • string2 - Hasil: 4.12814903259

Contoh 3

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

  • string1 - Hasil: 3.11899876595
  • string2 - Hasil: 2.78014397621

Hasil di atas adalah produk dengan hasil pengembalian terendah dari rata-rata: repeat(3, 2000000)

Contoh 3 dapat 3x lebih cepat dari Contoh 1 .

mbeacom
sumber
@kkurian Jika Anda membaca awal jawaban saya, ini hanyalah perbandingan dari solusi yang diusulkan sebelumnya di atas. Anda mungkin ingin mengomentari jawaban yang berasal ... stackoverflow.com/a/25183802/2560922
mbeacom
Oh, saya melihat ke mana Anda akan pergi dengan ini. Selesai!
kkurian
1
Harus mempertimbangkan Contoh 3, ketika berurusan dengan corpus besar.
HARSH NILESH PATHAK
Sah! Terima kasih telah mencatat.
mbeacom
dapatkah Anda membandingkan jawaban saya''.join([*filter(str.isalnum, string)])
Grijesh Chauhan
22

Python 2. *

Saya pikir hanya filter(str.isalnum, string)berfungsi

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

Python 3. *

Dalam Python3, filter( )fungsi akan mengembalikan objek yang dapat diubah (bukan string seperti di atas). Kita harus bergabung kembali untuk mendapatkan string dari isertable:

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

atau untuk lulus listdigunakan bergabung ( tidak yakin tetapi bisa sedikit cepat )

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

catatan: membongkar yang [*args]valid dari Python> = 3.5

Grijesh Chauhan
sumber
4
@Alexey benar, Dalam python3 map, filterdan reduce kembali objek itertable gantinya. Masih dalam Python3 + saya akan lebih suka ''.join(filter(str.isalnum, string)) (atau untuk lulus daftar digunakan bersama ''.join([*filter(str.isalnum, string)])) daripada jawaban yang diterima.
Grijesh Chauhan
Saya tidak yakin ''.join(filter(str.isalnum, string))perbaikan filter(str.isalnum, string), setidaknya untuk membaca. Apakah ini benar-benar cara Pythreenic (ya, Anda bisa menggunakan itu) untuk melakukan ini?
TheProletariat
1
@TheProletariat Intinya adalah hanyafilter(str.isalnum, string) tidak kembali string di Python3 sebagai filter( )di Python3 mengembalikan iterator bukan jenis argumen seperti Python-2 +.
Grijesh Chauhan
@GrijeshChauhan, saya pikir Anda harus memperbarui jawaban Anda untuk menyertakan rekomendasi Python2 dan Python3 Anda.
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

Anda dapat menambahkan lebih banyak karakter khusus dan itu akan diganti dengan '' tidak berarti apa-apa yaitu mereka akan dihapus.

pkm
sumber
16

Berbeda dengan orang lain yang menggunakan regex, saya akan mencoba untuk mengecualikan setiap karakter yang bukan yang saya inginkan, alih-alih menyebutkan secara eksplisit apa yang tidak saya inginkan.

Misalnya, jika saya ingin hanya karakter dari 'a ke z' (huruf besar dan kecil) dan angka, saya akan mengecualikan yang lainnya:

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

Ini berarti "mengganti setiap karakter yang bukan angka, atau karakter dalam rentang 'a ke z' atau 'A ke Z' dengan string kosong".

Bahkan, jika Anda memasukkan karakter khusus ^di tempat pertama regex Anda, Anda akan mendapatkan negasi.

Ekstra tip: Jika Anda juga perlu huruf kecil hasilnya, Anda dapat membuat regex lebih cepat dan lebih mudah, selama Anda tidak akan menemukan huruf besar setiap saat.

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

Dengan asumsi Anda ingin menggunakan regex dan Anda ingin / perlu kode Unicode-cognizant 2.x yang siap 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
sumber
7
s = re.sub(r"[-()\"#/@;:<>{}`+=~|.!?,]", "", s)
sneha
sumber
6

Pendekatan yang paling umum adalah menggunakan 'kategori' dari tabel unicodedata yang mengklasifikasikan setiap karakter tunggal. Misalnya kode berikut memfilter hanya karakter yang dapat dicetak berdasarkan kategorinya:

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

Lihatlah URL yang diberikan di atas untuk semua kategori terkait. Tentu saja Anda juga dapat memfilter menurut kategori tanda baca.

Andreas Jung
sumber
Ada apa dengan $di akhir setiap baris?
John Machin
Jika masalah salin & tempel, haruskah Anda memperbaikinya?
Olli
5

string.punctuation berisi karakter berikut:

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

Anda dapat menggunakan fungsi terjemahan dan maketrans untuk memetakan tanda baca ke nilai kosong (ganti)

import string

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

Keluaran:

'This is A test'
Vlad Bezden
sumber
4

Gunakan terjemahkan:

import string

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

Peringatan: Hanya berfungsi pada string ascii.

jjmurre
sumber
Perbedaan versi? Saya dapatkan TypeError: translate() takes exactly one argument (2 given)dengan 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 

sama dengan tanda kutip ganda. "" "

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

dan Anda akan melihat hasilnya sebagai

'askhnlaskdjalsdk

Dsw Wds
sumber
4
tunggu .... Anda mengimpor retetapi tidak pernah menggunakannya. replaceKriteria Anda hanya berfungsi untuk string spesifik ini. Bagaimana jika string Anda abc = "askhnl#$%!askdjalsdk"? Saya tidak berpikir akan bekerja pada apa pun selain #$%polanya. Mungkin ingin mengubahnya
JChao
0

Menghapus Tanda Baca, Angka, dan Karakter Khusus

Contoh: -

masukkan deskripsi gambar di sini

Kode

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

Hasil:- masukkan deskripsi gambar di sini

Terima kasih :)

Harish Kumawat
sumber
0

Untuk bahasa lain seperti Jerman, Spanyol, Denmark, Prancis dll yang berisi karakter khusus (seperti Jerman "Umlaute" sebagai ü, ä, ö) hanya menambahkan ini ke string pencarian regex:

Contoh untuk Bahasa Jerman:

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