¿Cómo ignorar los espacios en blanco en una cadena de asunto de expresión regular?

107

¿Existe una forma sencilla de ignorar el espacio en blanco en una cadena de destino cuando se buscan coincidencias con un patrón de expresión regular? Por ejemplo, si mi búsqueda es para "gatos", querría que "c ats" o "ca ts" coincidieran. No puedo eliminar el espacio en blanco de antemano porque necesito encontrar el índice de inicio y finalización de la coincidencia (incluido cualquier espacio en blanco) para resaltar esa coincidencia y cualquier espacio en blanco debe estar allí para fines de formato.

Steven
fuente

Respuestas:

124

Puede colocar caracteres de espacio \s*en blanco opcionales entre todos los demás caracteres de su expresión regular. Aunque concedido, será un poco largo.

/cats/ -> /c\s*a\s*t\s*s/

Sam Dufel
fuente
Gracias, parece que ese es el camino a seguir. Pero me acabo de dar cuenta de que solo quiero los caracteres de espacio en blanco opcionales si siguen una nueva línea. Entonces, por ejemplo, "c \ n ats" o "ca \ n ts" deberían coincidir. Pero no querría que "c ats" coincida si no hay una nueva línea. ¿Alguna idea sobre cómo podría hacerse?
Steven
@Steven, mira cómo lo hice a continuación, puedes adaptar fácilmente mi solución a casos tan específicos.
Bob
@chris Creo que esta expresión regular es tan estricta solo para gatos, que también se puede escribir para cualquier búsqueda de letras como esta: ^([a-z]\s*)+$
Sandeep Kaur
9

Abordar el comentario de Steven a la respuesta de Sam Dufel

Gracias, parece que ese es el camino a seguir. Pero me acabo de dar cuenta de que solo quiero los caracteres de espacio en blanco opcionales si siguen una nueva línea. Entonces, por ejemplo, "c \ n ats" o "ca \ n ts" deberían coincidir. Pero no querría que "c ats" coincida si no hay una nueva línea. ¿Alguna idea sobre cómo podría hacerse?

Esto debería funcionar:

/c(?:\n\s*)?a(?:\n\s*)?t(?:\n\s*)?s/

Consulte esta página para conocer todas las diferentes variaciones de 'gatos' que esto coincide.

También puede resolver esto usando condicionales , pero no son compatibles con la versión javascript de regex.

Aurimas
fuente
3
Muy feo. Debe haber una mejor manera.
james.garriss
Podría hacerlo más legible en la sintaxis JS (aunque la técnica funcionaría en otros idiomas) con:new RegExp('cats'.split('').join('(?:\n\s*)?'))
brianary
7

Si bien la respuesta aceptada es técnicamente correcta, un enfoque más práctico, si es posible, es simplemente eliminar los espacios en blanco tanto de la expresión regular como de la cadena de búsqueda.

Si desea buscar "mis gatos", en lugar de:

myString.match(/m\s*y\s*c\s*a\*st\s*s\s*/g)

Solo haz:

myString.replace(/\s*/g,"").match(/mycats/g)

Advertencia: No puede automatizar esto en la expresión regular simplemente reemplazando todos los espacios con cadenas vacías porque pueden ocurrir en una negación o invalidar su expresión regular.

Konrad Höffner
fuente
5

Puede poner \s*entre todos los caracteres de su cadena de búsqueda, por lo que si estuviera buscando un gato, usaríac\s*a\s*t\s*s\s*s

Es largo pero, por supuesto, podrías construir la cadena de forma dinámica.

Puedes verlo funcionando aquí: http://www.rubular.com/r/zzWwvppSpE

Kludge
fuente
3

Si solo desea permitir espacios, entonces

\bc *a *t *s\b

Deberías hacerlo. Para permitir también pestañas, use

\bc[ \t]*a[ \t]*t[ \t]*s\b

Elimine las \banclas si también desea buscar catsdentro de palabras como bobcatso catsup.

Tim Pietzcker
fuente
1

Este enfoque se puede usar para automatizar esto (la siguiente solución ejemplar está en Python, aunque obviamente se puede portar a cualquier idioma):

puede quitar el espacio en blanco de antemano Y guardar las posiciones de los caracteres que no son espacios en blanco para poder usarlos más adelante para averiguar las posiciones de los límites de la cadena coincidente en la cadena original como se muestra a continuación:

def regex_search_ignore_space(regex, string):
    no_spaces = ''
    char_positions = []

    for pos, char in enumerate(string):
        if re.match(r'\S', char):  # upper \S matches non-whitespace chars
            no_spaces += char
            char_positions.append(pos)

    match = re.search(regex, no_spaces)
    if not match:
        return match

    # match.start() and match.end() are indices of start and end
    # of the found string in the spaceless string
    # (as we have searched in it).
    start = char_positions[match.start()]  # in the original string
    end = char_positions[match.end()]  # in the original string
    matched_string = string[start:end]  # see

    # the match WITH spaces is returned.
    return matched_string

with_spaces = 'a li on and a cat'
print(regex_search_ignore_space('lion', with_spaces))
# prints 'li on'

Si desea ir más allá, puede construir el objeto de coincidencia y devolverlo en su lugar, por lo que el uso de este ayudante será más útil.

Y el rendimiento de esta función también se puede optimizar, por supuesto, este ejemplo es solo para mostrar el camino hacia una solución.

Beto
fuente