¿Las expresiones regulares del módulo re admiten límites de palabras (\ b)?

100

Mientras intentaba aprender un poco más sobre las expresiones regulares, un tutorial sugirió que puede usar el \bpara hacer coincidir el límite de una palabra. Sin embargo, el siguiente fragmento del intérprete de Python no funciona como se esperaba:

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

Debería haber sido un objeto de coincidencia si algo coincidía, pero lo es None.

¿La \bexpresión no es compatible con Python o la estoy usando mal?

corriente continua
fuente
31
Esto funcionará:re.search(r"\btwo\b", x)
Bolo
5
¿Por qué no estás usando cadenas "crudas"? r"\btwo\b"?
S.Lott
3
La gente se confunden a menudo acerca \b.
tchrist
Sí, Python lo hace, solo necesita una cadena sin procesar r'\b'para que el personaje se escape. (o de lo contrario, doble escape \\b, que es asqueroso)
smci

Respuestas:

85

¿Por qué no lo intentas?

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

Salida:

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

También se olvidó de mencionar que debería usar cadenas sin procesar en su código

>>> x = 'one two three'
>>> y = re.search(r"\btwo\b", x)
>>> y
<_sre.SRE_Match object at 0x100418a58>
>>> 
pyfunc
fuente
Interesante, gracias por el ejemplo de trabajo. ¿Tiene alguna idea de por qué el método que elegí no funciona? Los dos enfoques deberían ser iguales, excepto que en su enfoque solo está compilando una vez.
DC
1
@darren: Mira mi último ejemplo que mejora lo que hiciste. Proporcioné cadenas sin procesar para buscar.
pyfunc
1
ahh después de la sugerencia tuya y de Bolo, fue porque no estaba usando una cuerda cruda. ¡Gracias!
DC
9
-1: al revés. Las cadenas sin procesar deben ser las primeras. El otro asunto de construir una reexpresión con %sustitución de cuerdas es una mala tangente, irrelevante para esta pregunta en particular.
S.Lott
2
Mala respuesta. El código funciona, pero no hay explicación alguna.
Aran-Fey
88

Esto funcionará: re.search(r"\btwo\b", x)

Cuando se escribe "\b"en Python, es un solo carácter: "\x08". O escapar de la barra invertida de esta manera:

"\\b"

o escribe una cadena sin formato como esta:

r"\b"
Bolo
fuente
4
Esto realmente me ayudó ... Estaba luchando con una expresión regular parecida a pyspark r y no podía entender por qué \ b (límite de palabras) no funcionaba. Gracias
jb1t
17

Solo para explicar explícitamente por qué re.search("\btwo\b", x) no funciona, es porque \ben una cadena de Python es una abreviatura de un carácter de retroceso.

print("foo\bbar")
fobar

Entonces, el patrón "\btwo\b"busca un retroceso, seguido de twootro retroceso, que la cadena que está buscando en ( x = 'one two three') no tiene.

Para permitir re.search(o compile) interpretar la secuencia \bcomo un límite de palabra, escape las barras diagonales inversas ( "\\btwo\\b") o use una cadena sin formato para crear su patrón ( r"\btwo\b").

Bill el lagarto
fuente
10

Documentación de Python

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

\si

Coincide con la cadena vacía, pero solo al principio o al final de una palabra. Una palabra se define como una secuencia de caracteres alfanuméricos o de subrayado, por lo que el final de una palabra se indica mediante un espacio en blanco o un carácter no alfanumérico que no sea de subrayado. Tenga en cuenta que formalmente \ b se define como el límite entre un carácter \ w y un \ W (o viceversa), o entre \ w y el principio / final de la cadena, por lo que el conjunto preciso de caracteres que se consideran alfanuméricos depende en los valores de las banderas UNICODE y LOCALE. Por ejemplo, r '\ bfoo \ b' coincide con 'foo', 'foo.', '(Foo)', 'bar foo baz' pero no con 'foobar' o 'foo3'. Dentro de un rango de caracteres, \ b representa el carácter de retroceso, por compatibilidad con los literales de cadena de Python.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente