130

While trying to learn a little more about regular expressions, a tutorial suggested that you can use the \b to match a word boundary. However, the following snippet in the Python interpreter does not work as expected:

>>> x = 'one two three'
>>> y = re.search("\btwo\b", x)

It should have been a match object if anything was matched, but it is None.

Is the \b expression not supported in Python or am I using it wrong?

smci
  • 32,567
  • 20
  • 113
  • 146
D.C.
  • 15,340
  • 19
  • 71
  • 102
  • 38
    This will work: `re.search(r"\btwo\b", x)` – Bolo Oct 22 '10 at 08:39
  • 5
    Why aren't you using "raw" strings? `r"\btwo\b"`? – S.Lott Oct 22 '10 at 10:56
  • 4
    People are [often confused](http://stackoverflow.com/questions/4213800/is-there-something-like-a-counter-variable-in-regular-expression-replace/4214173#4214173) about `\b`. – tchrist Nov 18 '10 at 13:55
  • 2
    **Yes** Python does, you just need raw-string `r'\b'` so the character is escaped. (or else double-escape it `\\b`, which is yukky) – smci Jun 09 '20 at 09:35

5 Answers5

114

You should be using raw strings in your code

>>> x = 'one two three'
>>> y = re.search(r"\btwo\b", x)
>>> y
<_sre.SRE_Match object at 0x100418a58>
>>> 

Also, why don't you try

word = 'two'
re.compile(r'\b%s\b' % word, re.I)

Output:

>>> word = 'two'
>>> k = re.compile(r'\b%s\b' % word, re.I)
>>> x = 'one two three'
>>> y = k.search( x)
>>> y
<_sre.SRE_Match object at 0x100418850>
justhalf
  • 8,960
  • 3
  • 47
  • 74
pyfunc
  • 65,343
  • 15
  • 148
  • 136
  • Interesting, thanks for the working example. Do you have any insight as to why the method I chose doesn't work? The two approach should be the same, except that in your approach you are only compiling once. – D.C. Oct 22 '10 at 08:42
  • 1
    @darren: See my last example which just improves on what you did. I provided raw strings to search. – pyfunc Oct 22 '10 at 08:44
  • 1
    ahh after yours and Bolo's suggestion, it was because I wasn't using a raw string. Thanks! – D.C. Oct 22 '10 at 08:46
  • @darren: I provided this answer 13 minutes back :) – pyfunc Oct 22 '10 at 08:47
  • @pyfunc +1 for a nice answer, but I've decided to write a comment (and ultimately an answer) to distill the key point here: `"\b"` is not what @darren thought it is. – Bolo Oct 22 '10 at 08:58
  • 10
    -1: Backwards. The raw strings should be first. The other business of building an re expression with string `%` substitution is a bad tangent, irrelevant to this particular question. – S.Lott Oct 22 '10 at 10:57
  • 2
    Bad answer. The code works, but there's no explanation whatsoever. – Aran-Fey Jun 11 '18 at 13:08
107

This will work: re.search(r"\btwo\b", x)

When you write "\b" in Python, it is a single character: "\x08". Either escape the backslash like this:

"\\b"

or write a raw string like this:

r"\b"
Bolo
  • 11,542
  • 7
  • 41
  • 60
  • 4
    This really helped me... I was struggling with a pyspark rlike regular expression and couldn't figure out why the \b (word boundary) wasn't working. Thanks – jb1t Jun 17 '16 at 23:09
  • Thanks, I got caught by this too. But why does `\d` work fine without raw string but `\b` doesn't? – Quinn Comendant Dec 17 '20 at 21:45
  • The double backslash observation really got me out of a hole. Thank you. – dimButTries Nov 14 '21 at 14:09
  • @QuinnComendant because \d is not an escape sequence, see table at https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals – user1556435 Feb 10 '22 at 12:28
24

Just to explicitly explain why re.search("\btwo\b", x) doesn't work, it's because \b in a Python string is shorthand for a backspace character.

print("foo\bbar")
fobar

So the pattern "\btwo\b" is looking for a backspace, followed by two, followed by another backspace, which the string you're searching in (x = 'one two three') doesn't have.

To allow re.search (or compile) to interpret the sequence \b as a word boundary, either escape the backslashes ("\\btwo\\b") or use a raw string to create your pattern (r"\btwo\b").

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
10

Python documentation

https://docs.python.org/2/library/re.html#regular-expression-syntax

\b

Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of alphanumeric or underscore characters, so the end of a word is indicated by whitespace or a non-alphanumeric, non-underscore character. Note that formally, \b is defined as the boundary between a \w and a \W character (or vice versa), or between \w and the beginning/end of the string, so the precise set of characters deemed to be alphanumeric depends on the values of the UNICODE and LOCALE flags. For example, r'\bfoo\b' matches 'foo', 'foo.', '(foo)', 'bar foo baz' but not 'foobar' or 'foo3'. Inside a character range, \b represents the backspace character, for compatibility with Python’s string literals.

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
-1

just a note, for dynamic variable this will not work

x = 'one two three'
dy = "two"
y = re.search(r"\b" + dy + "\b", x)
print(y) # None

use r"\b" on left and right

x = 'one two three'
dy = "two"
y = re.search(r"\b" + dy + r"\b", x)
print(y) # <re.Match object; span=(4, 7), match='two'>
uingtea
  • 6,002
  • 2
  • 26
  • 40