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

236

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

user664546
источник

Ответы:

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.

Если вы настаиваете на использовании регулярных выражений, другие решения подойдут. Однако обратите внимание, что если это можно сделать без использования регулярного выражения, это лучший способ сделать это.

user225312
источник
7
В чем причина не использовать регулярные выражения в качестве практического правила?
Крис Датроу
@ChrisDutrow регулярные выражения медленнее, чем встроенные функции строки Python
Диего Наварро
Это работает только тогда, когда строка в Unicode . В противном случае он жалуется на то, что объект 'str' не имеет атрибута 'isalnum', 'isnumeric' и так далее.
NeoJi
10
@DiegoNavarro, за исключением того, что это не так, я сравнил isalnum()версии и с регулярным выражением, и с регулярным выражением на 50-75% быстрее
Франциско Кузо
2
Дополнительно: «Для 8-битных строк этот метод зависит от локали.»! Таким образом, альтернатива регулярному выражению строго лучше!
Антти Хаапала
232

Вот регулярное выражение, соответствующее строке символов, которые не являются буквами или цифрами:

[^A-Za-z0-9]+

Вот команда Python для подстановки регулярных выражений:

re.sub('[^A-Za-z0-9]+', '', mystring)
Энди Уайт
источник
10
ПОЦЕЛУЙ: Держи это просто глупо! Это короче и намного проще для чтения, чем решения без регулярных выражений, а также может быть быстрее. (Однако я бы добавил +квантификатор, чтобы немного повысить его эффективность.)
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 )

Если вы хотите пробелы между словами и числами, замените '' на ''

tuxErrante
источник
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 .

mbeacom
источник
@kkurian Если вы прочитали начало моего ответа, это всего лишь сравнение ранее предложенных решений. Вы можете прокомментировать исходный ответ ... stackoverflow.com/a/25183802/2560922
mbeacom
О, я вижу, куда ты идешь с этим. Готово!
ккурян
1
Необходимо учитывать пример 3, когда имеешь дело с большим корпусом.
ХАРАШ НИЛЕШ ПАТАХ
Действительно! Спасибо, что заметили.
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( )функция возвращает возвращаемый объект (вместо строки в отличие от описанной выше). Нужно присоединиться, чтобы получить строку из 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), по крайней мере, для чтения. Это действительно пифринский (да, вы можете использовать это) способ сделать это?
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())
Andrea
источник
9

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

Андреас Юнг
источник
Что с $в конце каждой строки?
Джон Мачин
Если это проблема копирования и вставки, то следует ли это исправить?
Олли
5

string.punctuation содержит следующие символы:

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

Вы можете использовать функции translate и 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 + ' ')

Предостережение: работает только для строк ascii.

jjmurre
источник
Разница версий? Я получаю TypeError: translate() takes exactly one argument (2 given)с py3.4
Мэтт Вилки
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

Dsw Wds
источник
4
подождите .... вы импортировали, reно никогда не использовали его. Ваши replaceкритерии работают только для этой конкретной строки. Что если ваша строка abc = "askhnl#$%!askdjalsdk"? Я не думаю, что будет работать на что-либо, кроме #$%шаблона. Может быть, хочу настроить это
JChao
0

Удаление знаков препинания, чисел и специальных символов

Пример :-

введите описание изображения здесь

Код

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

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

Спасибо :)

Хариш Кумават
источник
0

Для других языков , таких как немецкий, испанский, датский, французский и т.д. , которые содержат специальные символы (например , немецкий «Umlaute» , как ü, ä, ö) просто добавить их в поисковой строке регулярное выражение:

Пример для немецкого языка:

re.sub('[^A-ZÜÖÄa-z0-9]+', '', mystring)
petezurich
источник