Xóa tất cả các ký tự đặc biệt, dấu câu và dấu cách khỏi chuỗi


236

Tôi cần xóa tất cả các ký tự đặc biệt, dấu chấm câu và dấu cách khỏi một chuỗi để tôi chỉ có các chữ cái và số.

Câu trả lời:


351

Điều này có thể được thực hiện mà không cần regex:

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

Bạn có thể sử dụng 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.

Nếu bạn khăng khăng sử dụng regex, các giải pháp khác sẽ làm tốt. Tuy nhiên lưu ý rằng nếu có thể được thực hiện mà không sử dụng biểu thức chính quy, đó là cách tốt nhất để thực hiện.


7
Lý do không sử dụng regex như một quy tắc của ngón tay cái là gì?
Chris Dutrow

@ChrisDutrow regex chậm hơn các hàm dựng sẵn chuỗi python
Diego Navarro

Điều này chỉ hoạt động khi chuỗi ở unicode . Mặt khác, nó phàn nàn như đối tượng 'str' không có thuộc tính 'isalnum' 'isnumeric', v.v.
NeoJi

10
@DiegoNavarro ngoại trừ điều đó không đúng, tôi đã điểm chuẩn cả isalnum()phiên bản regex và regex và phiên bản regex nhanh hơn 50-75%
Francisco Couzo

2
Ngoài ra: "Đối với chuỗi 8 bit, phương thức này phụ thuộc vào miền địa phương."! Do đó, sự thay thế regex là hoàn toàn tốt hơn!
Antti Haapala

231

Dưới đây là biểu thức chính quy để khớp với một chuỗi ký tự không phải là chữ cái hoặc số:

[^A-Za-z0-9]+

Đây là lệnh Python để thực hiện thay thế regex:

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

10
KISS: Giữ nó đơn giản ngu ngốc! Điều này ngắn hơn và dễ đọc hơn nhiều so với các giải pháp phi regex và cũng có thể nhanh hơn. (Tuy nhiên, tôi sẽ thêm một bộ +định lượng để cải thiện hiệu quả của nó một chút.)
Ridgerunner

1
điều này cũng loại bỏ khoảng cách giữa các từ, "nơi tuyệt vời" -> "nơi tuyệt vời". Làm thế nào để tránh nó?
Reihan_amn

5
@Reihan_amn Đơn giản chỉ cần thêm một khoảng trắng vào biểu thức chính, để nó trở thành:[^A-Za-z0-9 ]+
Ostroon

1
@ andy-trắng bạn có thể vui lòng thêm khoảng trắng vào biểu thức chính quy trong câu trả lời không? Không gian không phải là một nhân vật đặc biệt ...
Ufos

3
Tôi đoán điều này không hoạt động với ký tự được sửa đổi trong các ngôn ngữ khác, như á , ö , ñ , v.v ... Tôi có đúng không? Nếu vậy, làm thế nào nó sẽ là regex cho nó?
HuLu ViCa

49

Đường ngắn hơn:

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

Nếu bạn muốn khoảng trắng giữa các từ và số thay thế '' bằng ''


3
Ngoại trừ việc _ ở trong \ w và là một nhân vật đặc biệt trong bối cảnh của câu hỏi này.
kkurian

Phụ thuộc vào ngữ cảnh - gạch dưới rất hữu ích cho tên tệp và các mã định danh khác, đến mức tôi không coi nó là một ký tự đặc biệt mà là một không gian được khử trùng. Tôi thường sử dụng phương pháp này.
Echelon

1
r'\W+'- hơi lạc đề (và rất phạm vi) nhưng tôi đề xuất một thói quen rằng tất cả các mẫu biểu thức chính là chuỗi thô
Bob Stein

2
Quy trình này không coi dấu gạch dưới (_) là một ký tự đặc biệt.
Md. Sabbir Ahmed

30

Sau khi thấy điều này, tôi đã quan tâm đến việc mở rộng các câu trả lời được cung cấp bằng cách tìm ra câu trả lời nào thực hiện trong ít thời gian nhất, vì vậy tôi đã xem qua và kiểm tra một số câu trả lời được đề xuất với timeithai chuỗi ví dụ:

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

ví dụ 1

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

  • string1 - Kết quả: 10.7061979771
  • string2 - Kết quả: 7.78372597694

Ví dụ 2

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

  • string1 - Kết quả: 7.10785102844
  • string2 - Kết quả: 4.12814903259

Ví dụ 3

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

  • string1 - Kết quả: 3.11899876595
  • string2 - Kết quả: 2,78014397621

Các kết quả trên là một sản phẩm có kết quả trả về thấp nhất từ ​​trung bình: repeat(3, 2000000)

Ví dụ 3 có thể nhanh hơn 3x so với ví dụ 1 .


@kkurian Nếu bạn đọc phần đầu câu trả lời của tôi, đây chỉ là so sánh các giải pháp được đề xuất trước đây. Bạn có thể muốn bình luận về câu trả lời có nguồn gốc ... stackoverflow.com/a/25183802/2560922
mbeacom

Ồ, tôi thấy bạn đang đi đâu với điều này. Làm xong!
kkurian

1
Phải xem xét ví dụ 3, khi xử lý khối lượng lớn.
HARSH NILESH PATHAK

Có hiệu lực! Cảm ơn đã lưu ý.
mbeacom

bạn có thể so sánh câu trả lời của tôi không''.join([*filter(str.isalnum, string)])
Grijesh Chauhan

22

Con trăn 2. *

Tôi nghĩ chỉ cần filter(str.isalnum, string)làm việc

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

Con trăn 3. *

Trong Python3, filter( )hàm sẽ trả về một đối tượng itertable (thay vì chuỗi không giống như ở trên). Người ta phải tham gia trở lại để có được một chuỗi từ itertable:

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

hoặc để listsử dụng tham gia ( không chắc chắn nhưng có thể nhanh một chút )

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

lưu ý: giải nén [*args]hợp lệ từ Python> = 3.5


4
@Alexey sửa, Trong python3 map, filterreduce lợi nhuận đối tượng itertable để thay thế. Vẫn trong Python3 + tôi sẽ thích ''.join(filter(str.isalnum, string)) (hoặc vượt qua danh sách sử dụng tham gia ''.join([*filter(str.isalnum, string)])) hơn câu trả lời được chấp nhận.
Grijesh Chauhan 15/03/18

Tôi không chắc chắn ''.join(filter(str.isalnum, string))là một sự cải thiện filter(str.isalnum, string), ít nhất là để đọc. Đây thực sự là cách Pythreenic (yeah, bạn có thể sử dụng cách đó) để làm điều này?
TheProletariat

1
@TheProletariat Vấn đề là chỉfilter(str.isalnum, string) không gửi lại chuỗi trong Python3 như filter( )trong Python3 trả về iterator chứ không phải là kiểu lập luận không giống như Python-2 +.
Grijesh Chauhan

@GrijeshChauhan, tôi nghĩ bạn nên cập nhật câu trả lời của mình để bao gồm cả khuyến nghị Python2 và 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

bạn có thể thêm ký tự đặc biệt hơn và nó sẽ được thay thế bằng '' nghĩa là không có gì tức là chúng sẽ bị xóa.


16

Khác với những người khác đã sử dụng regex, tôi sẽ cố gắng loại trừ mọi nhân vật không phải là điều tôi muốn, thay vì liệt kê rõ ràng những gì tôi không muốn.

Ví dụ: nếu tôi chỉ muốn các ký tự từ 'a đến z' (chữ hoa và chữ thường) và số, tôi sẽ loại trừ mọi thứ khác:

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

Điều này có nghĩa là "thay thế mọi ký tự không phải là số hoặc ký tự trong phạm vi 'a đến z' hoặc 'A thành Z' bằng một chuỗi trống".

Trong thực tế, nếu bạn chèn ký tự đặc biệt ^ở vị trí đầu tiên của regex của bạn, bạn sẽ nhận được phủ định.

Mẹo thêm: nếu bạn cũng cần viết thường kết quả, bạn có thể thực hiện regex nhanh hơn và dễ dàng hơn, miễn là bạn sẽ không tìm thấy bất kỳ chữ hoa nào ngay bây giờ.

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

9

Giả sử bạn muốn sử dụng regex và bạn muốn / cần mã 2.x nhận thức Unicode có sẵn 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

Cách tiếp cận chung nhất là sử dụng 'loại' của bảng unicodingata để phân loại từng ký tự. Ví dụ: các bộ lọc mã sau chỉ lọc các ký tự có thể in dựa trên danh mục của chúng:

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

Nhìn vào URL đã cho ở trên cho tất cả các danh mục liên quan. Tất nhiên bạn cũng có thể lọc theo các loại dấu chấm câu.


Có gì với $ở phần cuối của mỗi dòng?
John Machin

Nếu đó là vấn đề sao chép và dán, bạn có nên sửa nó không?
Olli

5

chuỗi. Dấu chấm câu chứa các ký tự sau:

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

Bạn có thể sử dụng các chức năng dịch và maketrans để ánh xạ dấu chấm câu thành các giá trị trống (thay thế)

import string

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

Đầu ra:

'This is A test'

4

Dùng dịch thuật:

import string

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

Hãy cẩn thận: Chỉ hoạt động trên chuỗi ascii.


Phiên bản khác biệt? Tôi nhận được TypeError: translate() takes exactly one argument (2 given)với 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 

giống như dấu ngoặc kép. "" "

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

và bạn sẽ thấy kết quả của bạn là

'hỏihnlaskdjalsdk


4
chờ đợi .... bạn đã nhập renhưng không bao giờ sử dụng nó replaceTiêu chí của bạn chỉ hoạt động cho chuỗi cụ thể này. Nếu chuỗi của bạn là abc = "askhnl#$%!askdjalsdk"gì? Tôi không nghĩ sẽ làm việc trên bất cứ thứ gì khác ngoài #$%mẫu. Có thể muốn điều chỉnh nó
JChao

0

Xóa dấu câu, số và ký tự đặc biệt

Thí dụ :-

nhập mô tả hình ảnh ở đây

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

Kết quả:- nhập mô tả hình ảnh ở đây

Cảm ơn :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.