ลบอักขระพิเศษเครื่องหมายวรรคตอนและช่องว่างทั้งหมดออกจากสตริง


236

ฉันต้องลบอักขระพิเศษเครื่องหมายวรรคตอนและช่องว่างทั้งหมดออกจากสตริงเพื่อให้ฉันมีตัวอักษรและตัวเลขเท่านั้น

คำตอบ:


351

สิ่งนี้สามารถทำได้โดยไม่ต้อง regex:

>>> 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.

หากคุณยืนยันในการใช้ regex โซลูชันอื่น ๆ จะทำได้ดี อย่างไรก็ตามโปรดทราบว่าหากสามารถทำได้โดยไม่ใช้นิพจน์ทั่วไปนั่นเป็นวิธีที่ดีที่สุดในการดำเนินการ


7
เหตุผลที่ไม่ใช้ regex เป็นกฎง่ายๆคืออะไร
Chris Dutrow

@ChrisDutrow regex ช้ากว่าฟังก์ชั่นในตัวของไพ ธ อนสตริง
Diego Navarro

ใช้งานได้เฉพาะเมื่อสตริงอยู่ในUnicodeเท่านั้น มิฉะนั้นจะบ่นเช่นวัตถุ 'str' ไม่มีแอตทริบิวต์ 'isalnum' 'isnumeric' และอื่น ๆ
NeoJi

10
@DiegoNavarro ยกเว้นที่ไม่เป็นความจริงฉันเปรียบเทียบทั้งรุ่นisalnum()และ regex และ regex หนึ่งเร็วขึ้น 50-75%
Francisco Couzo

2
นอกจากนี้: "สำหรับสตริง 8 บิตวิธีนี้ขึ้นอยู่กับโลแคล"! ดังนั้นทางเลือก regex จะดีกว่าอย่างเคร่งครัด!
Antti Haapala

232

นี่คือ regex เพื่อจับคู่สตริงของอักขระที่ไม่ใช่ตัวอักษรหรือตัวเลข:

[^A-Za-z0-9]+

นี่คือคำสั่ง Python เพื่อทำการทดแทน regex:

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

10
KISS: ทำให้มันโง่ง่าย ๆ ! นี่สั้นกว่าและอ่านง่ายกว่าโซลูชันที่ไม่ใช่ regex และอาจเร็วกว่าเช่นกัน (อย่างไรก็ตามฉันจะเพิ่มตัวขยาย+ปริมาณเพื่อปรับปรุงประสิทธิภาพของมันเล็กน้อย)
ridgerunner

1
สิ่งนี้จะลบช่องว่างระหว่างคำว่า "สถานที่ที่ดี" -> "สถานที่ที่ดี" จะหลีกเลี่ยงได้อย่างไร
Reihan_amn

5
@Reihan_amn เพียงแค่เพิ่มพื้นที่ที่จะ regex จึงกลายเป็น:[^A-Za-z0-9 ]+
ostroon

1
@ andy-white คุณสามารถเพิ่มพื้นที่ให้กับ regex ในคำตอบได้ไหม? พื้นที่ไม่ได้เป็นตัวละครพิเศษ ...
ยูเอฟโอ

3
ฉันเดาว่านี่จะไม่ทำงานกับตัวละครที่ถูกดัดแปลงในภาษาอื่นเช่นá , ö , ñเป็นต้นฉันถูกไหม? ถ้าเป็นเช่นนั้นจะเป็น regex ได้อย่างไร
HuLu ViCa

50

วิธีที่สั้นกว่า:

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

หากคุณต้องการเว้นวรรคระหว่างคำและตัวเลขแทน '' ด้วย ''


3
ยกเว้นว่า _ อยู่ใน \ w และเป็นอักขระพิเศษในบริบทของคำถามนี้
kkurian

ขึ้นอยู่กับบริบท - ขีดล่างมีประโยชน์อย่างมากสำหรับชื่อไฟล์และตัวระบุอื่น ๆ จนถึงจุดที่ฉันไม่ได้ถือว่าเป็นอักขระพิเศษ แต่เป็นพื้นที่ที่ถูกสุขอนามัยโดยทั่วไปฉันใช้วิธีนี้ด้วยตัวเอง
ระดับ

1
r'\W+'- ปิดหัวข้อเล็กน้อย (และอวดรู้มาก) แต่ฉันขอแนะนำให้นิสัยที่ทุกรูปแบบ regex เป็นสายอักขระดิบ
Bob Stein

2
ขั้นตอนนี้ไม่ถือว่าขีดล่าง (_) เป็นอักขระพิเศษ
Md. Sabbir Ahmed

30

หลังจากเห็นสิ่งนี้ฉันสนใจที่จะขยายคำตอบที่ได้รับจากการค้นหาว่ามีการประมวลผลใดในเวลาที่น้อยที่สุดดังนั้นฉันจึงไปตรวจสอบคำตอบที่เสนอบางคำtimeitกับสองตัวอย่าง:

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

ตัวอย่างที่ 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สามารถ 3x เร็วกว่าตัวอย่างที่ 1


@kkurian หากคุณอ่านคำตอบของฉันนี่เป็นเพียงการเปรียบเทียบโซลูชั่นที่เสนอก่อนหน้านี้ข้างต้น คุณอาจต้องการแสดงความคิดเห็นในคำตอบที่มา ... stackoverflow.com/a/25183802/2560922
mbeacom

โอ้ฉันเห็นว่าคุณกำลังจะไปกับสิ่งนี้ ทำ!
kkurian

1
ต้องพิจารณาตัวอย่างที่ 3 เมื่อต้องรับมือกับคลังข้อมูลขนาดใหญ่
HARSH NILESH PATHAK

ถูกต้อง! ขอบคุณที่สังเกต
mbeacom

คุณสามารถเปรียบเทียบคำตอบของฉันได้ไหม''.join([*filter(str.isalnum, string)])
Grijesh Chauhan

22

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ในการเข้าร่วม ( ไม่แน่ใจ แต่สามารถเร็วได้เล็กน้อย )

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

หมายเหตุ: การเปิดออกที่[*args]ถูกต้องจากPython> = 3.5


4
ที่ถูกต้อง @Alexey ใน python3 map, filterและreduce ผลตอบแทนวัตถุ itertable แทน ยังอยู่ใน Python3 + ฉันจะชอบ ''.join(filter(str.isalnum, string)) (หรือผ่านรายการในการเข้าร่วมใช้''.join([*filter(str.isalnum, string)])) มากกว่าคำตอบที่ยอมรับ
Grijesh Chauhan

ฉันไม่แน่ใจว่า''.join(filter(str.isalnum, string))จะปรับปรุงfilter(str.isalnum, string)อย่างน้อยอ่าน นี่เป็น Pythreenic (ใช่คุณสามารถใช้วิธีนี้) ทำสิ่งนี้ได้ไหม?
TheProletariat

1
@TheProletariat จุดคือเพียงแค่filter(str.isalnum, string)ไม่ได้ส่งกลับสตริงใน Python3 เป็นfilter( )ใน Python3 ส่งกลับ iterator มากกว่าประเภทอาร์กิวเมนต์แตกต่างจากงูหลาม-2 +.
Grijesh Chauhan

@GrijeshChauhan ฉันคิดว่าคุณควรอัปเดตคำตอบของคุณเพื่อรวมทั้งคำแนะนำ Python2 และ 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

คุณสามารถเพิ่มอักขระพิเศษเพิ่มเติมและจะถูกแทนที่ด้วย '' หมายความว่าไม่มีอะไรเช่นพวกเขาจะถูกลบออก


16

แตกต่างจากคนอื่น ๆ ที่ใช้ regex ฉันจะพยายามแยกตัวละครทุกตัวที่ไม่ใช่สิ่งที่ฉันต้องการแทนการระบุสิ่งที่ฉันไม่ต้องการอย่างชัดเจน

ตัวอย่างเช่นหากฉันต้องการเฉพาะอักขระจาก 'a ถึง z' (ตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก) และตัวเลขฉันจะยกเว้นทุกอย่างอื่น:

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

ซึ่งหมายความว่า "แทนที่อักขระทุกตัวที่ไม่ใช่ตัวเลขหรืออักขระในช่วง 'a ถึง z' หรือ 'A to Z' ด้วยสตริงว่าง"

ในความเป็นจริงถ้าคุณใส่อักขระพิเศษ^ในตำแหน่งแรกของ regex ของคุณคุณจะได้รับการปฏิเสธ

เคล็ดลับพิเศษ: หากคุณต้องการพิมพ์ผลลัพธ์ให้เล็กลงคุณสามารถทำให้ regex เร็วขึ้นและง่ายขึ้นตราบใดที่คุณไม่พบตัวพิมพ์ใหญ่ในตอนนี้

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

9

สมมติว่าคุณต้องการใช้ regex และคุณต้องการ / ต้องการโค้ด Unicode-cognizant 2.x ที่พร้อมใช้งาน 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

วิธีการทั่วไปที่สุดคือการใช้ 'หมวดหมู่' ของตาราง 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 ที่ให้ไว้ด้านบนสำหรับหมวดหมู่ที่เกี่ยวข้องทั้งหมด นอกจากนี้คุณยังสามารถกรองหลักสูตรตามหมวดหมู่วรรคตอน


มีอะไรกับ$ตอนท้ายของแต่ละเส้น?
John Machin

หากเป็นปัญหาการคัดลอกและวางคุณควรแก้ไขหรือไม่
Olli

5

string.punctuation มีอักขระดังต่อไปนี้:

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

คุณสามารถใช้ฟังก์ชั่นการแปลและ maketrans เพื่อแมปเครื่องหมายวรรคตอนกับค่าว่าง (แทนที่)

import string

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

เอาท์พุท:

'This is A test'

4

ใช้การแปล:

import string

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

Caveat: ใช้งานได้กับสตริง ascii เท่านั้น


ความแตกต่างของรุ่น? ฉันได้รับTypeError: translate() takes exactly one argument (2 given)กับ 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 

เช่นเดียวกับเครื่องหมายคำพูดคู่ "" "

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

และคุณจะเห็นผลลัพธ์ของคุณเป็น

'askhnlaskdjalsdk


4
รอ .... คุณนำเข้าreแต่ไม่เคยใช้ replaceเกณฑ์ของคุณใช้ได้กับสตริงเฉพาะนี้เท่านั้น ถ้าสตริงของคุณคือabc = "askhnl#$%!askdjalsdk"อะไร ฉันไม่คิดว่าจะทำงานกับสิ่งใดนอกจาก#$%รูปแบบ อาจต้องการปรับแต่งมัน
JChao

0

การลบเครื่องหมายวรรคตอนตัวเลขและอักขระพิเศษ

ตัวอย่าง: -

ป้อนคำอธิบายรูปภาพที่นี่

รหัส

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

ผลลัพธ์:- ป้อนคำอธิบายรูปภาพที่นี่

ขอบคุณ :)


0

สำหรับภาษาอื่น ๆ เช่นเยอรมัน, สเปน, เดนมาร์ก, ฝรั่งเศส ฯลฯ ที่มีอักขระพิเศษ (เช่นเยอรมัน "Umlaute" เป็นü, ä, ö) เพียงแค่เพิ่มเหล่านี้เพื่อสตริงการค้นหา regex นี้:

ตัวอย่างภาษาเยอรมัน:

re.sub('[^A-ZÜÖÄa-z0-9]+', '', mystring)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.