A Python regex to remove punctuation from a string is re.sub(r'[^\w\s]', '', text) — one line, eleven characters of pattern, and every comma, period, and quote disappears in a single pass. The catch is that this same pattern also swallows symbols like $, +, and = and eats emoji, because the negated character class treats anything that is not a word character or whitespace as expendable. For real text — product prices, social copy, multilingual paragraphs — that over-stripping is a bug, not a feature. Unicode solves it: punctuation is its own category, separate from symbols, and the Unicode-aware regex \p{P} targets only the seven punctuation subcategories while leaving currency signs, math operators, and emoji exactly where they were. If you want this precision without writing a single line of Python, the Remove Punctuation tool applies the same Unicode-verified rules in your browser, with toggles to protect word-internal apostrophes and hyphens that a strict regex would otherwise damage.

remove punctuation from string python regex
Python Regex: Remove Punctuation From Any String

The Quick Answer: A Working Python Regex for Punctuation

The fastest one-liner in Python is re.sub(r'[^\w\s]', '', text), which deletes every character that is not a word character or whitespace. Under Python 3, \w is Unicode-aware by default, so the pattern already covers letters from any script, but it still treats symbols and emoji as removable. The classic beginner example looks like this: import re; text = "Hello, world! It's $19.99 + tax."; clean = re.sub(r'[^\w\s]', '', text), which yields "Hello world Its 1999 tax". Notice two problems: the apostrophe disappeared from It's, leaving the contraction looking misspelled, and the $ and + were eaten along with the period, producing meaningless 1999 instead of 19.99. Both outcomes are predictable once you know what the regex is actually doing — it is not "remove punctuation"; it is "remove everything that is not a word or a space." If you want to keep the $ symbol, then the pattern needs to allow symbols through, and that is where most tutorials stop being helpful.

Many guides recommend string.punctuation instead, which is the constant !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~. The pattern becomes re.sub('[' + re.escape(string.punctuation) + ']', '', text) or str.translate(str.maketrans('', '', string.punctuation)). This is cleaner and faster, but it covers only ASCII punctuation — every full-width CJK mark, every smart quote, and every European dash sits outside the constant. If your text is purely English, the result is correct; if it isn't, you have shipped a silent bug.

Why a Plain Regex Breaks on Symbols and Emoji

The string ".+😀" — a period, a plus sign, and a grinning emoji — all fall into the same bucket under [^\w\s] because none of them is a word character or whitespace. From Python's perspective, they are equally ineligible, so they are equally deleted. That is fine for a synthetic test but disastrous for any text that mentions prices, math, or social copy. The actual Unicode categorization, which you can look up in the Unicode Character Database, splits this neatly: punctuation marks belong to the P categories (Connector, Dash, Opening, Closing, Initial quote, Final quote, Other), while symbols belong to the S categories (Math, Currency, Modifier, Other) and emoji live in symbol territory as well. A regex that ignores those distinctions will always over-strip.

A second issue is that [^\w\s] quietly misbehaves on mixed-language text. A sentence containing the full-width Chinese period U+3002 IDEOGRAPHIC FULL STOP — behaves differently from the ASCII period, and the full-width comma at U+FF0C needs to be handled explicitly. Authors of beginner tutorials rarely test on CJK text, so the bugs stay hidden until a user pastes a Chinese paragraph and gets a different result than the English tutorial promised.

This is also why a tool that purports to strip punctuation can be sold as fixing one of two distinct jobs: clean punctuation out of text, or clean everything that is not a letter or digit out of text. The second job eats symbols and emoji by design. The first job is what you actually want, and the regex has to be written more carefully to do it.

Going Unicode-Aware With \p{P} and the Unicode Standard

Python's built-in re module, despite supporting Unicode, does not natively accept \p{P} as a Unicode property escape the way JavaScript does. The MDN reference on Unicode character class escapes describes \p{P} as matching every Unicode punctuation character, which is exactly the scope you want — and JavaScript engines, plus the third-party Python regex module, both honour it. To get equivalent behaviour in pure CPython, the practical options are:

  • Build a translation table with str.translate and string.punctuation, which handles ASCII cleanly but misses CJK punctuation.
  • Use the third-party regex module, which does support \p{P} and gives you the same precision as a JavaScript regex with the u flag.
  • Manually enumerate the seven Unicode punctuation subcategories in a character class — a long, ugly range string that has to be kept in sync with new Unicode releases.

For most people writing a one-off clean-up script, this is the moment writing a regex stops feeling like a quick fix. The pattern is not a sentence any more; it is a maintenance contract.

How to Remove Punctuation Without Writing the Regex Yourself

If you would rather skip the Unicode literature and just clean the text, the Remove Punctuation tool does the same classification work in your browser. There is no script to host, no flag to forget, and no character class to maintain. The verified operating steps are:

  1. Paste the text you want to strip punctuation from into the input box.
  2. Decide whether apostrophes in contractions and hyphens in compound words should survive, and whether removed marks should become spaces instead of disappearing outright.
  3. Click Remove punctuation, check the removal count, and copy the result.

The tool strips exactly the seven Unicode punctuation subcategories — Connector, Dash, Opening, Closing, Initial quote, Final quote, and Other — and proves that scope by leaving $, +, =, ^, ©, currency signs and emoji untouched. If you also want symbols gone, the Special Characters Remover is the sibling tool that does that job; this page exists for the cases where it must not happen. Everything runs locally; nothing is uploaded, stored, or sent to an account, and a one-million-character paste processes in a single linear pass in milliseconds.

Protecting Contractions and Compound Words From the Strip

The genuinely tricky part of stripping punctuation is not the punctuation — it is the words that contain punctuation. don't, it's, state-of-the-art, and well-known are not "punctuation plus word"; they are words whose internal punctuation carries meaning. A blunt regex removes the apostrophe and the hyphens and silently turns these into dont, its, stateoftheart, and wellknown, which then look like spelling errors or merge with adjacent words.

The Remove Punctuation tool handles this with two toggles. The apostrophe toggle keeps the straight keyboard apostrophe and the curly typographic one inside contractions and possessives — both shapes of ', including U+2019 RIGHT SINGLE QUOTATION MARK — so don't stays don't instead of collapsing. The rule is "letters or digits on both sides," which means a quotation mark wrapped around a word is still removed. The hyphen toggle does the same for compound words. well-known and state-of-the-art keep their hyphens, and a date range like 2020-2021 survives, while a dash floating between spaces is still stripped. Both rules are word-internal by design, which has one honest consequence the documentation calls out rather than hides: a trailing possessive like the dogs' bowls loses its apostrophe, because nothing follows it.

What Happens to Numbers, Tabs, and Line Breaks

Stripping punctuation also strips decimal points and thousands separators, because the period in 9.99 and the comma in 1,000 are punctuation by Unicode's reckoning. That is what removing punctuation means: 9.99 becomes 999, 1,000 becomes 1000, and 2020-2021 survives only if the hyphen toggle protects the internal dash. If you need the pieces kept apart — for instance, to feed the result into a tokenizer that expects space-separated tokens — flip on the replace-with-space toggle. one,two,three then becomes one two three instead of onetwothree, and the resulting runs of spaces are tidied to single spaces per line without ever merging lines together.

Tabs and line breaks are never touched in either mode, so the shape of your text survives a clean strip. That matters when you are cleaning multi-paragraph input and do not want a single call to flatten the structure. The removal counter reports exactly how many code points were removed, and the operation is idempotent — running the output through again changes nothing, so it is safe to chain with other cleaners or to apply it twice if a downstream step introduces new punctuation you did not anticipate.

CharacterUnicode categoryStripped by a plain regexStripped by Remove Punctuation
Comma , U+002CPunctuation / OtherYesYes
Period . U+002EPunctuation / OtherYesYes
Dollar sign $ U+0024Symbol / CurrencyYesNo
Plus sign + U+002BSymbol / MathYesNo
Emoji 😀 U+1F600Symbol / OtherYesNo
Apostrophe in don't U+0027Punctuation, internalYesNo when toggle on
Hyphen in state-of-the-art U+002DPunctuation, internalYesNo when toggle on
Full-width period 。 U+3002Punctuation / OtherNo by defaultYes

Choosing Between a Python Regex and the Browser Tool

Write the regex when you need the strip embedded in a larger pipeline — a data-preprocessing script, a batch job, a CI check. The one-liner re.sub(r'[^\w\s]', '', text) is fine for ASCII-only English text where symbol-over-stripping is acceptable. For anything multilingual, mixed with currency or emoji, or contractually obligated to leave $19.99 readable, switch to a Unicode property regex through the regex module or hand-curate the seven punctuation subcategories.

Use the Remove Punctuation tool when the cleaning is a one-off or an ad-hoc step before pasting the text somewhere else. It encodes the Unicode classification once, maintains it as the standard evolves, and gives you three toggles that no single regex line covers. Either way, the rule is the same: punctuation goes, symbols stay, contractions and compounds survive on purpose, and you should never ship a cleaner that quietly mangles numbers or emoji without telling you.

If you're weighing options, How to Get a Random Word in Python Without Code covers this in detail.

If you're weighing options, How to Remove Special Characters in Google Sheets Cells covers this in detail.