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


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.