Видаліть зі спеціального рядка всі спеціальні символи, розділові знаки та пробіли


236

Мені потрібно видалити всі спеціальні символи, розділові знаки та пробіли з рядка, щоб у мене залишилися лише літери та цифри.

Відповіді:


351

Це можна зробити без регулярного вираження:

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

Якщо ви наполягаєте на використанні регексу, інші рішення стануть чудовими. Однак зауважте, що якщо це можна зробити без використання регулярного виразу, це найкращий спосіб зробити це.


7
Яка причина не використовувати регулярне вираження як правило?
Кріс Дутроу

Регекс @ChrisDutrow повільніше, ніж вбудовані функції в питонну струну
Дієго Наварро

Це працює лише тоді, коли рядок знаходиться в unicode . В іншому випадку він скаржиться, що об'єкт "str" ​​не має атрибута "isalnum" "isnumeric" тощо.
NeoJi

10
@DiegoNavarro, за винятком того, що це неправда, я оцінив isalnum()і версії, і
регекс

2
Додатково: "Для 8-бітових рядків цей метод залежить від локалі."! Таким чином, альтернатива регулярного вираження суворо краща!
Антті Хаапала

232

Ось регулярний вираз, який відповідає рядку символів, який не є буквою чи цифрою:

[^A-Za-z0-9]+

Ось команда Python для заміни регулярних виразів:

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

10
KISS: Нехай це буде просто тупо! Це коротше і набагато простіше для читання, ніж рішення, що не регенерують, а також може бути швидшим. (Однак я б додав +кількісний показник, щоб трохи підвищити його ефективність.)
ridgerunner

1
це також видаляє пробіли між словами, "велике місце" -> "чудовий". Як цього уникнути?
Reihan_amn

5
@Reihan_amn Просто додайте пробіл у регулярний вираз, щоб він став:[^A-Za-z0-9 ]+
ostroon

1
@ andy-white чи можете ви додайте простір у регулярний вираз у відповіді? Космос не є особливим персонажем ...
Ufos

3
Я думаю, це не працює з модифікованим символом в інших мовах, таких як á , ö , ñ тощо. Я прав? Якщо так, то як би це було регулярним виразом?
HuLu ViCa

50

Коротший шлях:

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

Якщо ви хочете, щоб пробіли між словами та цифрами замінили "" на ""


3
За винятком того, що _ знаходиться у \ w і є особливим символом у контексті цього питання.
kkurian

Залежить від контексту - підкреслення дуже корисно для імен і інших ідентифікаторів, до того, що я не ставлюсь до нього як до особливого символу, а до більш санізованого простору. Я зазвичай використовую цей метод сам.
Ешелон

1
r'\W+'- трохи поза темою (і дуже педантично), але я пропоную звичку, щоб усі шаблони регулярних виразів були сирими рядками
Боб Штейн

2
Ця процедура не розглядає підкреслення (_) як особливий символ.
Пані Саббір Ахмед

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 може бути в 3 рази швидшим, ніж приклад 1 .


@kkurian Якщо ви читаєте початок моєї відповіді, це лише порівняння раніше запропонованих рішень. Ви можете прокоментувати ініціює відповідь ... stackoverflow.com/a/25183802/2560922
mbeacom

О, я бачу, куди ти йдеш із цим. Готово!
kkurian

1
Потрібно врахувати Приклад 3, коли йдеться про великий корпус.
HARSH NILESH PATHAK

Дійсно! Дякуємо, що зауважили.
mbeacom

чи можна порівняти мою відповідь''.join([*filter(str.isalnum, string)])
Гріеш Чаухан

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( )функція повертає ітерабельний об'єкт (замість рядка на відміну від вище). Треба приєднатися назад, щоб отримати рядок з ітерабету:

''.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), принаймні, для читання. Це справді пітрейєричний (так, ви можете використовувати це) спосіб це зробити?
TheProletariat

1
@TheProletariat Суть полягає лише вfilter(str.isalnum, string) тому, що не повертайте рядок у Python3, як filter( )у Python-3 повертає ітератор, а не тип аргументу на відміну від Python-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

Я би спробував виключити кожен символ, який не є тим, що я хочу, замість того, щоб явно перераховувати те, що я не хочу.

Наприклад, якщо я хочу лише символів з 'a до z' (верхній і нижній регістр) та числа, я б виключив все інше:

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

Це означає "замінити кожен символ, який не є числом, або символ у діапазоні" a до z "або" A до Z "порожнім рядком".

Насправді, якщо ви вставите спеціального символу ^на перше місце свого регексу, ви отримаєте заперечення.

Додаткова порада: якщо ви також повинні рядкові результат, ви можете зробити регулярний вираз ще швидше і простіше, поки ви не знайдете ні в верхньому регістрі в даний час.

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

9

Припустимо, що ви хочете використовувати регулярний вираз і вам потрібен / потрібний Unicode-пізнавальний код 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-адресу вище для всіх пов’язаних категорій. Ви також можете фільтрувати за розділовими категоріями.


Що вказується $в кінці кожного рядка?
Джон Махін

Якщо це проблема копіювання та вставки, чи потрібно це виправити?
Оллі

5

string.punctuation містить такі символи:

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

Ви можете використовувати функції перекладу та макетрансу для відображення розділових знаків на порожні значення (заміни)

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

Результат: - введіть тут опис зображення

Дякую :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.