문자열에서 구두점을 제거하는 가장 좋은 방법


636

다음보다 간단한 방법이 있어야합니다.

import string
s = "string. With. Punctuation?" # Sample string 
out = s.translate(string.maketrans("",""), string.punctuation)

있습니까?


3
나에게 매우 간단 해 보인다. 왜 바꾸고 싶습니까? 더 쉽게 원한다면 방금 함수로 작성한 것을 래핑하십시오.
Hannes Ovrén

2
글쎄, 방금 str.translate의 부작용을 사용하여 작업을 수행하는 것은 일종의 해킹처럼 보였습니다. str.strip (chars)와 같이 내가 놓친 경계 대신 전체 문자열에서 작동하는 것이 있다고 생각했습니다.
로렌스 존스턴

2
데이터에도 의존합니다. 이름의 일부로 밑줄이있는 서버 이름이있는 데이터에서 이것을 사용하면 (일부 일반적인 장소) 잘못 될 수 있습니다. 데이터와 그 데이터가 무엇인지 알고 있는지 확인하십시오. 또는 사소한 문제의 하위 집합으로 끝날 수 있습니다.
EBGreen

54
구두점이라고하는 것에 따라 다릅니다. " The temperature in the O'Reilly & Arbuthnot-Smythe server's main rack is 40.5 degrees."에는 정확히 하나의 문장 부호 문자, 두 번째 ""가 포함됩니다. "
John Machin

37
string.punctuation영어 이외의 구두점을 포함하지 않는 사람은 아무도 없습니다 . 。 ,!? : ד”〟등을 생각하고 있습니다.
Clément

답변:


929

효율성 측면에서 이길 수는 없습니다

s.translate(None, string.punctuation)

더 높은 버전의 Python의 경우 다음 코드를 사용하십시오.

s.translate(str.maketrans('', '', string.punctuation))

C에서 룩업 테이블을 사용하여 원시 문자열 작업을 수행하고 있습니다.

속도가 걱정되지 않으면 다른 옵션은 다음과 같습니다.

exclude = set(string.punctuation)
s = ''.join(ch for ch in s if ch not in exclude)

이것은 각 문자로 s.replace보다 빠르지 만 아래 타이밍에서 볼 수 있듯이 정규 표현식이나 string.translate와 같은 순수하지 않은 파이썬 접근법은 수행하지 않습니다. 이러한 유형의 문제의 경우 가능한 낮은 수준에서 문제를 해결하면 효과가 있습니다.

타이밍 코드 :

import re, string, timeit

s = "string. With. Punctuation"
exclude = set(string.punctuation)
table = string.maketrans("","")
regex = re.compile('[%s]' % re.escape(string.punctuation))

def test_set(s):
    return ''.join(ch for ch in s if ch not in exclude)

def test_re(s):  # From Vinko's solution, with fix.
    return regex.sub('', s)

def test_trans(s):
    return s.translate(table, string.punctuation)

def test_repl(s):  # From S.Lott's solution
    for c in string.punctuation:
        s=s.replace(c,"")
    return s

print "sets      :",timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000)
print "regex     :",timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000)
print "translate :",timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000)
print "replace   :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000)

결과는 다음과 같습니다.

sets      : 19.8566138744
regex     : 6.86155414581
translate : 2.12455511093
replace   : 28.4436721802

27
타이밍 정보 덕분에, 나는 저 자신과 같은 일을 생각하고 있었지만 당신은 내가했던 것보다 더 잘 작성되었으며 이제는 내가 쓰고 싶은 미래의 타이밍 코드를위한 템플릿으로 사용할 수 있습니다 :).
Lawrence Johnston

29
좋은 대답입니다. 테이블을 제거하여 단순화 할 수 있습니다. 문서는 "문자를 삭제하는 번역에 대해서는 테이블 인수를 없음으로 설정"이라고 말합니다 ( docs.python.org/library/stdtypes.html#str.translate )
Alexandros Marinos

3
translate ()는 str 및 unicode 객체에 대해 다르게 작동하므로 항상 동일한 데이터 유형으로 작업하고 있는지 확인해야하지만이 답변의 접근 방식은 두 가지 모두에 대해 동일하게 작동하므로 편리합니다.
Richard J

36
Python3에서는 ? table = string.maketrans("","")로 바꿔야합니다 table = str.maketrans({key: None for key in string.punctuation}).
SparkAndShine

19
Python 3.6부터 토론을 업데이트하는 regex것이 이제 가장 효율적인 방법입니다! 번역보다 거의 2 배 빠릅니다. 또한 세트와 교체가 더 이상 나쁘지 않습니다! 둘 다 4 배 이상 향상되었습니다.
Ryan Soklaski

143

정규 표현식은 알고 있다면 충분히 간단합니다.

import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]','',s)

4
@Outlier 설명 : (^)이 아닌 단어 문자 또는 공백을 빈 문자열로 바꿉니다. 예를 들어, \ w는 밑줄과도 일치합니다.
Matthias

4
@SIslam 나는 유니 코드 플래그가 설정된 유니 코드로 작동한다고 생각합니다 s = re.sub(r'[^\w\s]','',s, re.UNICODE). 리눅스에서 파이썬 3으로 테스트하면 타밀 문자 தமிழ்를 사용하는 플래그가 없어도 작동합니다.
Matthias

@ Matthias Mac에서 Python 3.6.5로 코드를 사용해 보았습니다. 타밀 문자 출력이 약간 다르게 보입니다. 입력 தமிழ்가 தமழ이됩니다. 나는 타밀어에 대해 전혀 모른다. 그것이 예상되는지 확실하지 않다.
shiouming

70

사용법의 편의를 위해 Python 2와 Python 3의 문자열에서 스트라이핑 구두점에 대한 메모를 요약합니다. 자세한 설명은 다른 답변을 참조하십시오.


파이썬 2

import string

s = "string. With. Punctuation?"
table = string.maketrans("","")
new_s = s.translate(table, string.punctuation)      # Output: string without punctuation

파이썬 3

import string

s = "string. With. Punctuation?"
table = str.maketrans(dict.fromkeys(string.punctuation))  # OR {key: None for key in string.punctuation}
new_s = s.translate(table)                          # Output: string without punctuation

51
myString.translate(None, string.punctuation)

4
아, 이것을 시도했지만 모든 경우에 작동하지는 않습니다. myString.translate (string.maketrans ( "", ""), string.punctuation)은 정상적으로 작동합니다.
Aidan Kane

12
에 대한주의 str파이썬 3에서, 그리고 unicode파이썬 2에서 deletechars인수가 지원되지 않습니다.
agf

4
myString.translate (string.maketrans ( "", ""), string.punctuation)은 유니 코드 문자열과 작동하지 않습니다 (어려운 방법)
Marc Maxmeister

44
TypeError: translate() takes exactly one argument (2 given):(
Brian Tingle

3
@BrianTingle : 내 의견에서 Python 3 코드를보십시오 (한 인수를 전달합니다). 이 링크를 따라 가면 유니 코드그 파이썬 3에
jfs

29

나는 보통 다음과 같은 것을 사용합니다 :

>>> s = "string. With. Punctuation?" # Sample string
>>> import string
>>> for c in string.punctuation:
...     s= s.replace(c,"")
...
>>> s
'string With Punctuation'

2
추한 원 라이너 : reduce(lambda s,c: s.replace(c, ''), string.punctuation, s).
jfs

1
위대한, 그러나 더 긴 하이픈과 같은 어떤 문장을 제거하지 않습니다
Vladimir Stazhilov

25

string.punctuationASCII 만입니다 ! 더 정확한 (그러나 훨씬 더 느린) 방법은 unicodedata 모듈을 사용하는 것입니다.

# -*- coding: utf-8 -*-
from unicodedata import category
s = u'String — with -  «punctation »...'
s = ''.join(ch for ch in s if category(ch)[0] != 'P')
print 'stripped', s

다른 유형의 문자도 일반화하고 제거 할 수 있습니다.

''.join(ch for ch in s if category(ch)[0] not in 'SP')

또한 ~*+§$관점에 따라 "마침표"일 수도 있고 아닐 수도있는 문자를 제거합니다 .


3
당신은 할 수 :regex.sub(ur"\p{P}+", "", text)
JFS

불행히도, 같은 것들은 ~문장 부호 범주에 속하지 않습니다. 기호 범주도 테스트해야합니다.
CJ Jackson

24

가족과 더 친숙하다면 더 간단 할 필요는 없지만 다른 방법입니다.

import re, string
s = "string. With. Punctuation?" # Sample string 
out = re.sub('[%s]' % re.escape(string.punctuation), '', s)

1
string.punctuation에 시퀀스,-가 있기 때문에 작동합니다. 적절한 오름차순, 간격 없음, ASCII 순서로. Python에는이 권한이 있지만 string.punctuation의 하위 집합을 사용하려고하면 "-"가 놀라워 서 중단 점이 될 수 있습니다.
S.Lott

2
사실, 여전히 잘못되었습니다. "\]"시퀀스는 이스케이프 (동시에 우연히]를 닫지 않아 다른 실패를 우회)로 취급되지만 \ 이스케이프되지 않은 상태로 남습니다. 이를 방지하려면 re.escape (string.punctuation)를 사용해야합니다.
Brian

1
예, 간단하게 유지하기 위해 예제에서 작동했기 때문에 생략했지만 포함해야합니다.
Vinko Vrsalovic

13

Python 3 str또는 Python 2 unicode값의 str.translate()경우 사전 만 사용합니다. 해당 매핑에서 코드 포인트 (정수)가 조회되고 매핑 된 항목 None이 제거됩니다.

그런 다음 구두점을 제거하려면 다음을 사용하십시오.

import string

remove_punct_map = dict.fromkeys(map(ord, string.punctuation))
s.translate(remove_punct_map)

dict.fromkeys()클래스 메소드는 사소한 모든 설정 값을 매핑을 만들 수 있습니다 None키의 순서에 따라.

ASCII 문장 부호뿐만 아니라 모든 문장 부호 를 제거하려면 테이블이 약간 커야합니다. JF Sebastian의 답변 (Python 3 버전)을 참조하십시오 .

import unicodedata
import sys

remove_punct_map = dict.fromkeys(i for i in range(sys.maxunicode)
                                 if unicodedata.category(chr(i)).startswith('P'))

유니 코드를 지원 string.punctuation하기에는 충분하지 않습니다. 내 답변
jfs

@ JFSebastian : 실제로, 내 대답은 최고 투표와 동일한 문자를 사용하고있었습니다. Python 3 버전의 테이블을 추가했습니다.
Martijn Pieters

최상위 투표 답변은 ASCII 문자열에만 작동합니다. 귀하의 답변은 명시 적으로 유니 코드 지원을 주장합니다.
jfs

1
@ JFSebastian : 유니 코드 문자열에서 작동합니다. ASCII 문장 부호를 제거합니다. 나는 그것이 모든 구두점을 제거한다고 주장하지 않았다 . :-) 요점은 unicode객체 대 Python 2 str객체에 대한 올바른 기술을 제공하는 것이 었습니다 .
Martijn Pieters

12

string.punctuation현실 세계에서 일반적으로 사용되는 많은 문장 부호를 그리워합니다. 비 ASCII 구두점에 적합한 솔루션은 어떻습니까?

import regex
s = u"string. With. Some・Really Weird、Non?ASCII。 「(Punctuation)」?"
remove = regex.compile(ur'[\p{C}|\p{M}|\p{P}|\p{S}|\p{Z}]+', regex.UNICODE)
remove.sub(u" ", s).strip()

개인적으로, 이것이 파이썬의 문자열에서 구두점을 제거하는 가장 좋은 방법이라고 생각합니다.

  • 모든 유니 코드 문장 부호를 제거합니다
  • 쉽게 수정할 수 있습니다. 예를 들어 \{S}문장 부호를 제거하려면를 제거 할 수 있지만 기호는 다음과 같이 유지하십시오 $.
  • 유지하려는 항목과 제거하려는 항목에 대해 구체적으로 지정할 수 있습니다 (예 : \{Pd}대시 만 제거).
  • 이 정규식은 공백도 정규화합니다. 탭, 캐리지 리턴 및 기타 홀수를 멋진 단일 공백에 매핑합니다.

이것은 Wikipedia에서 더 많은 것을 읽을 수 있는 유니 코드 문자 속성을 사용합니다 .


9

아직이 답변을 보지 못했습니다. 정규식을 사용하십시오. 단어 문자 ( \w) 및 숫자 문자 ( \d) 이외의 모든 문자 와 공백 문자 ( \s)를 제거합니다.

import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(ur'[^\w\d\s]+', '', s)

1
\d의 하위 집합이므로 중복 \w됩니다.
blhsing

숫자 문자는 Word 문자의 하위 집합으로 간주됩니까? 나는 단어 문자가 실제 단어를 구성 할 수있는 어떤 문자라고 생각했다.
Blairg23

예, 정규식에서 "단어"에는 알파벳, 숫자 및 밑줄이 포함됩니다. \w다음 문서 의 설명을 참조하십시오 : docs.python.org/3/library/re.html
blhsing

8

다음은 Python 3.5의 한 줄짜리입니다.

import string
"l*ots! o(f. p@u)n[c}t]u[a'ti\"on#$^?/".translate(str.maketrans({a:None for a in string.punctuation}))

7

이것은 최선의 해결책은 아니지만 이것이 내가 한 방법입니다.

import string
f = lambda x: ''.join([i for i in x if i not in string.punctuation])

6

내가 쓴 함수는 다음과 같습니다. 매우 효율적이지 않지만 간단하며 원하는 문장 부호를 추가하거나 제거 할 수 있습니다.

def stripPunc(wordList):
    """Strips punctuation from list of words"""
    puncList = [".",";",":","!","?","/","\\",",","#","@","$","&",")","(","\""]
    for punc in puncList:
        for word in wordList:
            wordList=[word.replace(punc,'') for word in wordList]
    return wordList

5
import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(r'[^a-zA-Z0-9\s]', '', s)

ASCII 문자에서만 작동하는 것 같습니다.
avirr

5

업데이트와 마찬가지로 Python 3에서 @Brian 예제를 다시 작성하고 함수 내부에서 정규식 컴파일 단계를 이동하도록 변경했습니다. 여기에서 제 생각은 기능을 작동시키는 데 필요한 모든 단일 단계에 대한 시간이었습니다. 아마도 분산 컴퓨팅을 사용하고 있으며 직원간에 정규식 객체를 공유 할 수 없으며 re.compile각 작업자마다 단계를 수행 해야합니다 . 또한 파이썬 3에 대해 두 가지 다른 구현의 maketrans 시간을 궁금합니다.

table = str.maketrans({key: None for key in string.punctuation})

vs

table = str.maketrans('', '', string.punctuation)

또한 set을 사용하는 또 다른 방법을 추가하여 교차 횟수를 활용하여 반복 횟수를 줄였습니다.

이것은 완전한 코드입니다.

import re, string, timeit

s = "string. With. Punctuation"


def test_set(s):
    exclude = set(string.punctuation)
    return ''.join(ch for ch in s if ch not in exclude)


def test_set2(s):
    _punctuation = set(string.punctuation)
    for punct in set(s).intersection(_punctuation):
        s = s.replace(punct, ' ')
    return ' '.join(s.split())


def test_re(s):  # From Vinko's solution, with fix.
    regex = re.compile('[%s]' % re.escape(string.punctuation))
    return regex.sub('', s)


def test_trans(s):
    table = str.maketrans({key: None for key in string.punctuation})
    return s.translate(table)


def test_trans2(s):
    table = str.maketrans('', '', string.punctuation)
    return(s.translate(table))


def test_repl(s):  # From S.Lott's solution
    for c in string.punctuation:
        s=s.replace(c,"")
    return s


print("sets      :",timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000))
print("sets2      :",timeit.Timer('f(s)', 'from __main__ import s,test_set2 as f').timeit(1000000))
print("regex     :",timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000))
print("translate :",timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000))
print("translate2 :",timeit.Timer('f(s)', 'from __main__ import s,test_trans2 as f').timeit(1000000))
print("replace   :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000))

이것은 내 결과입니다.

sets      : 3.1830138750374317
sets2      : 2.189873124472797
regex     : 7.142953420989215
translate : 4.243278483860195
translate2 : 2.427158243022859
replace   : 4.579746678471565

4
>>> s = "string. With. Punctuation?"
>>> s = re.sub(r'[^\w\s]','',s)
>>> re.split(r'\s*', s)


['string', 'With', 'Punctuation']

2
자세한 내용으로 편집하십시오. 검색 가능한 콘텐츠가 포함되어 있지 않으며 누군가 "이 작업을 시도해야하는 이유"를 설명하지 않기 때문에 코드 전용 및 "이것을 시도하십시오"답변은 권장되지 않습니다.
Paritosh

4

정규식이없는 솔루션이 있습니다.

import string

input_text = "!where??and!!or$$then:)"
punctuation_replacer = string.maketrans(string.punctuation, ' '*len(string.punctuation))    
print ' '.join(input_text.translate(punctuation_replacer).split()).strip()

Output>> where and or then
  • 문장 부호를 공백으로 바꿉니다.
  • 단어 사이의 여러 공백을 단일 공백으로 교체
  • strip ()을 사용하여 후행 공백을 제거하십시오.

4

하나의 라이너는 매우 엄격한 경우에 도움이 될 수 있습니다.

''.join([c for c in s if c.isalnum() or c.isspace()])

2
#FIRST METHOD
#Storing all punctuations in a variable    
punctuation='!?,.:;"\')(_-'
newstring='' #Creating empty string
word=raw_input("Enter string: ")
for i in word:
     if(i not in punctuation):
                  newstring+=i
print "The string without punctuation is",newstring

#SECOND METHOD
word=raw_input("Enter string: ")
punctuation='!?,.:;"\')(_-'
newstring=word.translate(None,punctuation)
print "The string without punctuation is",newstring


#Output for both methods
Enter string: hello! welcome -to_python(programming.language)??,
The string without punctuation is: hello welcome topythonprogramminglanguage

2
with open('one.txt','r')as myFile:

    str1=myFile.read()

    print(str1)


    punctuation = ['(', ')', '?', ':', ';', ',', '.', '!', '/', '"', "'"] 

for i in punctuation:

        str1 = str1.replace(i," ") 
        myList=[]
        myList.extend(str1.split(" "))
print (str1) 
for i in myList:

    print(i,end='\n')
    print ("____________")

0

왜 아무도 이것을 사용하지 않습니까?

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

너무 느린?


공백도 제거됩니다.
Georgy

0

유니 코드를 고려하십시오. python3에서 코드가 확인되었습니다.

from unicodedata import category
text = 'hi, how are you?'
text_without_punc = ''.join(ch for ch in text if not category(ch).startswith('P'))

-1

Python을 사용하여 텍스트 파일에서 중지 단어를 제거하십시오.

print('====THIS IS HOW TO REMOVE STOP WORS====')

with open('one.txt','r')as myFile:

    str1=myFile.read()

    stop_words ="not", "is", "it", "By","between","This","By","A","when","And","up","Then","was","by","It","If","can","an","he","This","or","And","a","i","it","am","at","on","in","of","to","is","so","too","my","the","and","but","are","very","here","even","from","them","then","than","this","that","though","be","But","these"

    myList=[]

    myList.extend(str1.split(" "))

    for i in myList:

        if i not in stop_words:

            print ("____________")

            print(i,end='\n')

-2

나는 다음과 같은 기능을 사용하고 싶다 :

def scrub(abc):
    while abc[-1] is in list(string.punctuation):
        abc=abc[:-1]
    while abc[0] is in list(string.punctuation):
        abc=abc[1:]
    return abc

1
이것은 시작과 끝에서 문자를 제거합니다. abc.strip(string.punctuation)대신 사용하십시오 . 중간에 이러한 문자 제거되지 않습니다 .
Martijn Pieters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.