823

It seems like there should be a simpler way than:

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

Is there?

Georgy
  • 12,464
  • 7
  • 65
  • 73
Redwood
  • 66,744
  • 41
  • 126
  • 187
  • 4
    Seems pretty straightforward to me. Why do you want to change it? If you want it easier just wrap what you just wrote in a function. – Hannes Ovrén Nov 05 '08 at 17:38
  • 3
    Well, it just seemed kind of hackish to be be using kind of a side effect of str.translate to be doing the work. I was thinking there might be something more like str.strip(chars) that worked on the entire string instead of just the boundaries that I had missed. – Redwood Nov 05 '08 at 18:00
  • 2
    Depends on the data too. Using this on data where there are server names with underscores as part of the name (pretty common some places) could be bad. Just be sure that you know the data and what it conatains or you could end up with a subset of the clbuttic problem. – EBGreen Nov 05 '08 at 18:10
  • 64
    Depends also on what you call punctuation. "`The temperature in the O'Reilly & Arbuthnot-Smythe server's main rack is 40.5 degrees.`" contains exactly ONE punctuation character, the second "." – John Machin Mar 08 '10 at 21:49
  • 43
    I'm surprised no one mentioned that `string.punctuation` doesn't include non-English punctuation at all. I'm thinking about 。,!?:ד”〟, and so on. – Clément Jan 03 '13 at 15:40
  • 2
    Doesn't work with a unicode string? – Sergey Orshanskiy Feb 28 '15 at 04:25
  • 2
    @JohnMachin you're forgetting that [`' '` is punctuation](https://en.wikipedia.org/wiki/Space_(punctuation)). – Wayne Werner May 01 '17 at 16:42
  • 2
    As of python 3.1 (to at least 3.8.3), you'll want: `str.maketrans("","", string.punctuation)` per [this documentation](https://docs.python.org/3.3/library/stdtypes.html?highlight=maketrans#str.maketrans) with the change [documented in 3.1](https://docs.python.org/3/whatsnew/3.1.html) – Brownbat May 02 '20 at 16:16
  • Most of the discussion here is Python 2, [this question is similar](https://stackoverflow.com/questions/11066400/remove-punctuation-from-unicode-formatted-strings/21635971#21635971) but has superior Python 3 answers. – David Jones Nov 10 '20 at 11:13
  • I didn't see the solution `s.strip(string.punctuation)`; doesn't it answer the question? What am I missing? – Itamar Mushkin Jul 13 '22 at 13:40
  • It's unclear what the problem/qualifications are here; as such this question is currently off-topic. What is not simple enough about the method used? Please clarify in objective terms what you consider to be too complex about this. Is one line too many? Is it the number of functions required to achieve it? Is it a particular function you'd rather avoid? Etc. – TylerH Aug 16 '22 at 15:40
  • @Clément [Here's a good unicode-aware answer](https://stackoverflow.com/a/7268456/1048186) – Josiah Yoder Aug 30 '22 at 15:31
  • @Brownbat And by Python 3, you mean "Unicode-aware." My previous comment links to an answer to this question that is Unicode-aware and mentions both the 'S' (symbols) and 'P' (punctuation) unicode categories. – Josiah Yoder Aug 30 '22 at 15:33

32 Answers32

1244

From an efficiency perspective, you're not going to beat

s.translate(None, string.punctuation)

For higher versions of Python use the following code:

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

It's performing raw string operations in C with a lookup table - there's not much that will beat that but writing your own C code.

If speed isn't a worry, another option though is:

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

This is faster than s.replace with each char, but won't perform as well as non-pure python approaches such as regexes or string.translate, as you can see from the below timings. For this type of problem, doing it at as low a level as possible pays off.

Timing code:

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)

This gives the following results:

sets      : 19.8566138744
regex     : 6.86155414581
translate : 2.12455511093
replace   : 28.4436721802
Ashish Cherian
  • 367
  • 1
  • 3
  • 15
Brian
  • 116,865
  • 28
  • 107
  • 112
  • 35
    Thanks for the timing info, I was thinking about doing something like that myself, but yours is better written than anything I would have done and now I can use it as a template for any future timing code I want to write:). – Redwood Nov 05 '08 at 19:57
  • 30
    Great answer. You can simplify it by removing the table. The docs say: "set the table argument to None for translations that only delete characters" (http://docs.python.org/library/stdtypes.html#str.translate) – Alexandros Marinos Jul 01 '11 at 21:24
  • 1
    Using a list comprehension for the `''.join()` would make it a little faster, but not fast enough to beat the `regex` or `translate`. See [list comprehension without \[ \], Python](http://stackoverflow.com/a/9061024) for why that is so. – Martijn Pieters Nov 08 '13 at 12:13
  • 3
    worth noting too that translate() behaves differently for str and unicode objects, so you need to be sure you're always working with the same datatype, but the approach in this answer works equally well for both, which is handy. – Richard J Jan 16 '15 at 09:35
  • 41
    In Python3, `table = string.maketrans("","")` should be replaced with `table = str.maketrans({key: None for key in string.punctuation})`? – SparkAndShine May 13 '16 at 23:36
  • What's the purpose of doing `set(string.punctuation)`? It only has unique values to begin with. – mlissner Aug 08 '16 at 15:03
  • 2
    @mlissner - efficiency. It it's a list/string, you need to do a linear scan to find out whether the letter is in the string. With a set or dictionary though, it'll generally be faster (except for really small strings) since it doesn't have to check every value. – Brian Sep 27 '16 at 14:13
  • 1
    @sparkandshine Yes, except you have to map the ordinals of each key to the replacement character, so in Python 3 it would be `s.translate({ord(c): None for c in string.punctuation})`. – Galen Long Jan 26 '17 at 16:49
  • 27
    To update the discussion, as of Python 3.6, `regex` is now the most efficient method! It is almost 2x faster than translate. Also, sets and replace are no longer so bad! They are both improved by over a factor of 4 :) – Ryan Soklaski Jul 24 '17 at 22:35
  • 3
    In Python 3, the translation table can also be created by `table = str.maketrans('', '', string.punctuation)` https://docs.python.org/3/library/stdtypes.html#str.maketrans – RyanLeiTaiwan Mar 18 '18 at 16:11
  • 1
    >>> s.translate(None, string.punctuation) Traceback (most recent call last): File "", line 1, in TypeError: str.translate() takes exactly one argument (2 given) in python3, i think this answer needs updating – Coder Jan 08 '21 at 23:17
  • `TypeError: translate() takes exactly one argument (2 given)` for `s.translate(None, string.punctuation)` – The Singularity Oct 05 '21 at 11:40
  • 1
    @Luke You used one of the Python 3 versions of `str.maketrans()` suggested above, right? Notice that the punctation set has been baked into that table. So remove the second argument. – Bob Kline Oct 05 '21 at 12:56
  • On Python 3.7.3 I get timings of 2.299 for sets, 0.751 for regex, 0.926 for translate, and 3.630 for replace. So regex does indeed edge out translate, but not by much. – Bob Kline Oct 05 '21 at 13:00
  • @JohnD I am unable to update the original answer, so I provided a Python 3 update separately below. – Bob Kline Oct 05 '21 at 13:32
  • For anybody reading this thread, I wanted to mention that the accumulator method used in `test_set()` will actually be *slower* than the replace method for appreciably large input strings. Iterating over a small list of unique characters to remove with `str.replace()` in a string of thousands of characters will be much faster than the filtered `"".join()` technique. – ddejohn Oct 17 '21 at 19:35
  • can someone explain to me why str.maketrans needs three arguments to return a dictionary? – user12711 Sep 28 '22 at 16:20
  • Just a heads up: This will remove punctuations, you should replace it with a blank/white space or it should be a little more specific. With "real text" this will also lead to merged words, because people tend to forget a whitespace after e.g. commas or dots. – n.r. Oct 04 '22 at 12:56
199

Regular expressions are simple enough, if you know them.

import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]','',s)
Eratosthenes
  • 2,280
  • 1
  • 14
  • 11
  • 4
    @Outlier Explanation: replaces not (^) word characters or spaces with the empty string. Be careful though, the \w matches underscore too usually for example. – Matthias Feb 03 '16 at 15:28
  • 6
    @SIslam I think it will work with unicode with the unicode flag set, i.e. `s = re.sub(r'[^\w\s]','',s, re.UNICODE)`. Testing it with python 3 on linux it works even without the flag using tamil letters, தமிழ். – Matthias Feb 03 '16 at 15:31
  • 1
    @Matthias I tried the code with Python 3.6.5 on Mac, the Tamil letters output looks a bit different, input தமிழ் becomes தமழ. I have no knowledge about Tamil, not sure if that's expected. – shiouming May 28 '19 at 02:45
  • 1
    @Matthias It gets confused with word boundaries while working with UNICODE Bengali text and gives wrong words no matter UNICODE flag is used or not. – hafiz031 Sep 09 '20 at 13:04
89

For the convenience of usage, I sum up the note of striping punctuation from a string in both Python 2 and Python 3. Please refer to other answers for the detailed description.


Python 2

import string

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

Python 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
SparkAndShine
  • 17,001
  • 22
  • 90
  • 134
  • It's interesting that this solution (in particular the OR {key: None for...} option) allows to control what you want to insert in place of punctuation, which may be spaces (for this use key: " " instead of key: None). – Pablo Oct 15 '21 at 09:22
52
myString.translate(None, string.punctuation)
pyrou
  • 545
  • 4
  • 2
  • 4
    ah, I tried this but it doesn't work in all cases. myString.translate(string.maketrans("",""), string.punctuation) works fine. – Aidan Kane Aug 12 '10 at 12:30
  • 12
    Note that for `str` in Python 3, and `unicode` in Python 2, the `deletechars` argument is not supported. – agf Apr 14 '12 at 00:36
  • 2
    @agf: you still can [use `.translate()` to remove punctuation even in Unicode and py3k cases](http://stackoverflow.com/a/11066687/4279) using dictionary argument. – jfs Aug 28 '12 at 07:53
  • 4
    myString.translate(string.maketrans("",""), string.punctuation) will NOT work with unicode strings (found out the hard way) – Marc Maxmeister Jul 25 '14 at 19:25
  • 2
    @MarcMaxson: `myString.translate(str.maketrans("", "", string.punctuation))` does work for Unicode strings on Python 3. Though `string.punctuation` includes only ascii punctuation there. Click [the link in my previous comment](http://stackoverflow.com/a/11066687/4279). It shows how to remove all punctuation (including Unicode one). – jfs Oct 01 '14 at 08:56
  • 58
    `TypeError: translate() takes exactly one argument (2 given)` :( – Brian Tingle Apr 23 '15 at 18:35
  • 3
    @BrianTingle: look at the Python 3 code in my comment (it passes one argument). [Follow the link, to see Python 2 code that works with unicode](http://stackoverflow.com/a/11066687/4279) and [its Python 3 adaptation](http://stackoverflow.com/a/21635971/4279) – jfs Jul 15 '15 at 17:21
34

Not necessarily simpler, but a different way, if you are more familiar with the re family.

import re, string
s = "string. With. Punctuation?" # Sample string 
out = re.sub('[%s]' % re.escape(string.punctuation), '', s)
Vinko Vrsalovic
  • 330,807
  • 53
  • 334
  • 373
  • 1
    Works because string.punctuation has the sequence ,-. in proper, ascending, no-gaps, ASCII order. While Python has this right, when you try to use a subset of string.punctuation, it can be a show-stopper because of the surprise "-". – S.Lott Nov 05 '08 at 17:49
  • 2
    Actually, its still wrong. The sequence "\\]" gets treated as an escape (coincidentally not closing the ] so bypassing another failure), but leaves \ unescaped. You should use re.escape(string.punctuation) to prevent this. – Brian Nov 05 '08 at 18:15
  • 1
    Yes, I omitted it because it worked for the example to keep things simple, but you are right that it should be incorporated. – Vinko Vrsalovic Nov 05 '08 at 23:21
34

string.punctuation is ASCII only! A more correct (but also much slower) way is to use the unicodedata module:

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

You can generalize and strip other types of characters as well:

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

It will also strip characters like ~*+§$ which may or may not be "punctuation" depending on one's point of view.

wim
  • 338,267
  • 99
  • 616
  • 750
Björn Lindqvist
  • 19,221
  • 20
  • 87
  • 122
  • 4
    You could: [`regex.sub(ur"\p{P}+", "", text)`](http://stackoverflow.com/a/11066687/4279) – jfs Aug 11 '12 at 12:07
  • 1
    Unfortunately, things like `~` are not part of the punctuation category. You need to also test for the Symbols category as well. – C.J. Jackson Oct 06 '19 at 04:08
32

I usually use something like this:

>>> s = "string. With. Punctuation?" # Sample string
>>> import string
>>> for c in string.punctuation:
...     s= s.replace(c,"")
...
>>> s
'string With Punctuation'
S.Lott
  • 384,516
  • 81
  • 508
  • 779
16

For Python 3 str or Python 2 unicode values, str.translate() only takes a dictionary; codepoints (integers) are looked up in that mapping and anything mapped to None is removed.

To remove (some?) punctuation then, use:

import string

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

The dict.fromkeys() class method makes it trivial to create the mapping, setting all values to None based on the sequence of keys.

To remove all punctuation, not just ASCII punctuation, your table needs to be a little bigger; see J.F. Sebastian's answer (Python 3 version):

import unicodedata
import sys

remove_punct_map = dict.fromkeys(i for i in range(sys.maxunicode)
                                 if unicodedata.category(chr(i)).startswith('P'))
Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • To support Unicode, `string.punctuation` is not enough. See [my answer](http://stackoverflow.com/a/11066687/4279) – jfs Sep 30 '14 at 20:57
  • @J.F.Sebastian: indeed, my answer was just using the same characters as the top-voted one. Added a Python 3 version of your table. – Martijn Pieters Sep 30 '14 at 21:08
  • the top-voted answer works only for ascii strings. Your answer claims explicitly the Unicode support. – jfs Oct 01 '14 at 08:53
  • 1
    @J.F.Sebastian: it works for Unicode strings. It strips ASCII punctuation. I never claimed it strips *all* punctuation. :-) The point was to provide the correct technique for `unicode` objects vs. Python 2 `str` objects. – Martijn Pieters Oct 01 '14 at 09:02
15

string.punctuation misses loads of punctuation marks that are commonly used in the real world. How about a solution that works for non-ASCII punctuation?

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

Personally, I believe this is the best way to remove punctuation from a string in Python because:

  • It removes all Unicode punctuation
  • It's easily modifiable, e.g. you can remove the \{S} if you want to remove punctuation, but keep symbols like $.
  • You can get really specific about what you want to keep and what you want to remove, for example \{Pd} will only remove dashes.
  • This regex also normalizes whitespace. It maps tabs, carriage returns, and other oddities to nice, single spaces.

This uses Unicode character properties, which you can read more about on Wikipedia.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zach
  • 29,791
  • 35
  • 142
  • 201
  • 1
    This line actually does not work: `remove = regex.compile(ur'[\p{C}|\p{M}|\p{P}|\p{S}|\p{Z}]+', regex.UNICODE)` – John Stud Jun 29 '20 at 00:09
  • @JohnStud Breaks in later versions of Python 3 because now all strings default to support unicode already. Can remove the 'u' from lines 2, 3, and 4 and it works. – Joel Wigton Dec 15 '21 at 22:57
12

I haven't seen this answer yet. Just use a regex; it removes all characters besides word characters (\w) and number characters (\d), followed by a whitespace character (\s):

import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(ur'[^\w\d\s]+', '', s)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Blairg23
  • 11,334
  • 6
  • 72
  • 72
  • 3
    `\d` is redundant since it is a subset of `\w`. – blhsing Jan 10 '19 at 18:37
  • Number characters are considered a subset of Word characters? I thought a Word character was any character that could construct a real word, e.g. a-zA-Z? – Blairg23 Jan 10 '19 at 20:55
  • Yes, a "word" in regex includes alphabets, numbers and underscore. Please see the description for `\w` in the documentation: https://docs.python.org/3/library/re.html – blhsing Jan 10 '19 at 21:10
10

Here's a one-liner for 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}))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tim P
  • 415
  • 3
  • 11
10

This might not be the best solution however this is how I did it.

import string
f = lambda x: ''.join([i for i in x if i not in string.punctuation])
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
David Vuong
  • 101
  • 1
  • 2
  • That's a great solution but I'm not sure that `string.punctuation` covers all possible Unicode punctuation marks. – ingyhere Jul 28 '23 at 17:58
7

Here is a function I wrote. It's not very efficient, but it is simple and you can add or remove any punctuation that you desire:

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dr.Tautology
  • 416
  • 1
  • 8
  • 19
7
import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(r'[^a-zA-Z0-9\s]', '', s)
m81
  • 2,217
  • 5
  • 31
  • 47
6

A one-liner might be helpful in not very strict cases:

''.join([c for c in s if c.isalnum() or c.isspace()])
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dom Grey
  • 101
  • 1
  • 4
6
>>> s = "string. With. Punctuation?"
>>> s = re.sub(r'[^\w\s]','',s)
>>> re.split(r'\s*', s)


['string', 'With', 'Punctuation']
  • 2
    Please edit with more information. Code-only and "try this" answers are discouraged, because they contain no searchable content, and don't explain why someone should "try this". – Paritosh Aug 24 '16 at 07:29
6

Just as an update, I rewrote the @Brian example in Python 3 and made changes to it to move regex compile step inside of the function. My thought here was to time every single step needed to make the function work. Perhaps you are using distributed computing and can't have regex object shared between your workers and need to have re.compile step at each worker. Also, I was curious to time two different implementations of maketrans for Python 3

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

vs

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

Plus I added another method to use set, where I take advantage of intersection function to reduce number of iterations.

This is the complete code:

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

This is my results:

sets      : 3.1830138750374317
sets2      : 2.189873124472797
regex     : 7.142953420989215
translate : 4.243278483860195
translate2 : 2.427158243022859
replace   : 4.579746678471565
krinker
  • 1,072
  • 1
  • 9
  • 23
5

Here's a solution without regex.

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
  • Replaces the punctuations with spaces
  • Replace multiple spaces in between words with a single space
  • Remove the trailing spaces, if any with strip()
ngub05
  • 566
  • 1
  • 8
  • 15
5

Why none of you use this?

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

Too slow?

Dehua Li
  • 462
  • 1
  • 5
  • 8
5

I was looking for a really simple solution. here's what I got:

import re 

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

print(s)
'string  With  Punctuation '
aloha
  • 4,554
  • 6
  • 32
  • 40
4
# 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
Animeartist
  • 1,047
  • 1
  • 10
  • 21
4

Here's one other easy way to do it using RegEx

import re

punct = re.compile(r'(\w+)')

sentence = 'This ! is : a # sample $ sentence.' # Text with punctuation
tokenized = [m.group() for m in punct.finditer(sentence)]
sentence = ' '.join(tokenized)
print(sentence) 
'This is a sample sentence'

Zain Sarwar
  • 1,226
  • 8
  • 10
3
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 ("____________")
twasbrillig
  • 17,084
  • 9
  • 43
  • 67
3

Try that one :)

regex.sub(r'\p{P}','', s)
Vivian
  • 335
  • 2
  • 10
2

The question does not have a lot of specifics, so the approach I took is to come up with a solution with the simplest interpretation of the problem: just remove the punctuation.

Note that solutions presented don't account for contracted words (e.g., you're) or hyphenated words (e.g., anal-retentive)...which is debated as to whether they should or shouldn't be treated as punctuations...nor to account for non-English character set or anything like that...because those specifics were not mentioned in the question. Someone argued that space is punctuation, which is technically correct...but to me it makes zero sense in the context of the question at hand.

# using lambda
''.join(filter(lambda c: c not in string.punctuation, s))

# using list comprehension
''.join('' if c in string.punctuation else c for c in s)
Dexter Legaspi
  • 3,192
  • 1
  • 35
  • 26
1

Apparently I can't supply edits to the selected answer, so here's an update which works for Python 3. The translate approach is still the most efficient option when doing non-trivial transformations.

Credit for the original heavy lifting to @Brian above. And thanks to @ddejohn for his excellent suggestion for improvement to the original test.

#!/usr/bin/env python3

"""Determination of most efficient way to remove punctuation in Python 3.

Results in Python 3.8.10 on my system using the default arguments:

set       : 51.897
regex     : 17.901
translate :  2.059
replace   : 13.209
"""

import argparse
import re
import string
import timeit

parser = argparse.ArgumentParser()
parser.add_argument("--filename", "-f", default=argparse.__file__)
parser.add_argument("--iterations", "-i", type=int, default=10000)
opts = parser.parse_args()
with open(opts.filename) as fp:
    s = fp.read()
exclude = set(string.punctuation)
table = str.maketrans("", "", string.punctuation)
regex = re.compile(f"[{re.escape(string.punctuation)}]")

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

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

def test_translate(s):
    return s.translate(table)

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

opts = dict(globals=globals(), number=opts.iterations)
solutions = "set", "regex", "translate", "replace"
for solution in solutions:
    elapsed = timeit.timeit(f"test_{solution}(s)", **opts)
    print(f"{solution:<10}: {elapsed:6.3f}")
Bob Kline
  • 304
  • 1
  • 14
  • 1
    These tests are really not all that meaningful. For the sake of completeness, add tests for larger input strings, say like a few KBs large text file. The `str.translate` pulls ahead pretty quickly as `s` grows. – ddejohn Oct 17 '21 at 19:38
  • 1
    @ddejohn Excellent point. My original purpose was to respond to the users who were frustrated that they couldn't figure out how to get @Brian's original script to run under Python 3.x, but I can see that your suggestion improves the value of his original test significantly. And in fact, even `replace` beats out `regex` when the test is scaled up this way, and by a healthy margin. – Bob Kline Oct 18 '21 at 13:57
1

For serious natural language processing (NLP), you should let a library like SpaCy handle punctuation through tokenization, which you can then manually tweak to your needs.

For example, how do you want to handle hyphens in words? Exceptional cases like abbreviations? Begin and end quotes? URLs? IN NLP it's often useful to separate out a contraction like "let's" into "let" and "'s" for further processing.

SpaCy example tokenization

qwr
  • 9,525
  • 5
  • 58
  • 102
0

Considering unicode. Code checked in 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'))
Rajan saha Raju
  • 794
  • 7
  • 13
0

You can also do this:

import string
' '.join(word.strip(string.punctuation) for word in 'text'.split())
mohannatd
  • 51
  • 1
  • 2
0

When you deal with the Unicode strings, I suggest using PyPi regex module because it supports both Unicode property classes (like \p{X} / \P{X}) and POSIX character classes (like [:name:]).

Just install the package by typing pip install regex (or pip3 install regex) in your terminal and hit ENTER.

In case you need to remove punctuation and symbols of any kind (that is, anything other than letters, digits and whitespace) you can use

regex.sub(r'[\p{P}\p{S}]', '', text)  # to remove one by one
regex.sub(r'[\p{P}\p{S}]+', '', text) # to remove all consecutive punctuation/symbols with one go
regex.sub(r'[[:punct:]]+', '', text)  # Same with a POSIX character class

See a Python demo online:

import regex

text = 'भारत India <><>^$.,,! 002'
new_text = regex.sub(r'[\p{P}\p{S}\s]+', ' ', text).lower().strip()
# OR
# new_text = regex.sub(r'[[:punct:]\s]+', ' ', text).lower().strip()

print(new_text)
# => भारत india 002

Here, I added a whitespace \s pattern to the character class

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
-1

Remove stop words from the text file using 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')
GilZ
  • 6,418
  • 5
  • 30
  • 40
-3

I like to use a function like this:

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
    This is stripping characters from the start and end; use `abc.strip(string.punctuation)` instead for that. It won't remove such characters *in the middle*. – Martijn Pieters Feb 08 '16 at 21:13
  • never mind if the function does it or not, the unnecessary use of side effects and modifying the list while traversing it is just recipe for disaster. – Dexter Legaspi Aug 13 '21 at 17:23