 <p>I would use <a href="http://www.regular-expressions.info/lookaround.html" rel="nofollow">negative lookahead</a> like below,</p> <pre><code>&gt;&gt;&gt; re.sub(r'(?!-)\W', r' ', 'black-white') 'black-white' &gt;&gt;&gt; re.sub(r'(?!-)\W', r' ', 'black#white') 'black white' </code></pre> <p><code>(?!-)\W</code> the negative lookahead at the start asserts that the character we are going to match would be any from the <code>\W</code> (non-word character list) but not of hyphen <code>-</code> . It's like a kind of substraction, that is <code>\W - character present inside the negative lookahead</code> (ie. hyphen).</p> <p><a href="https://regex101.com/r/sS1qO8/2" rel="nofollow">DEMO</a></p>