Como ignorar espaços em branco em uma string de assunto de expressão regular?

107

Existe uma maneira simples de ignorar o espaço em branco em uma string de destino ao pesquisar correspondências usando um padrão de expressão regular? Por exemplo, se minha pesquisa for por "gatos", eu gostaria que "c ats" ou "ca ts" correspondessem. Não posso remover o espaço em branco de antemão porque preciso encontrar o índice inicial e final da correspondência (incluindo qualquer espaço em branco) para destacar essa correspondência e qualquer espaço em branco precisa estar lá para fins de formatação.

Steven
fonte

Respostas:

124

Você pode colocar caracteres de espaço \s*em branco opcionais entre todos os outros caracteres em sua regex. Embora concedido, será um pouco demorado.

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

Sam Dufel
fonte
Obrigado, parece que esse é o caminho a percorrer. Mas acabei de perceber que só quero os caracteres de espaço em branco opcionais se eles seguirem uma nova linha. Portanto, por exemplo, "c \ n ats" ou "ca \ n ts" deve corresponder. Mas não gostaria que "c ats" correspondessem se não houvesse nova linha. Alguma ideia de como isso pode ser feito?
Steven
@Steven, veja como fiz abaixo, você pode facilmente adaptar minha solução para tais casos específicos.
Bob
@chris, eu acho, este regex é tão estrito apenas para gatos, ele também pode ser escrito para qualquer pesquisa de letras como esta: ^([a-z]\s*)+$
Sandeep Kaur
9

Dirigindo o comentário de Steven à resposta de Sam Dufel

Obrigado, parece que esse é o caminho a percorrer. Mas acabei de perceber que só quero os caracteres de espaço em branco opcionais se eles seguirem uma nova linha. Portanto, por exemplo, "c \ n ats" ou "ca \ n ts" deve corresponder. Mas não gostaria que "c ats" correspondessem se não houvesse nova linha. Alguma ideia de como isso pode ser feito?

Isso deve resolver o problema:

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

Veja esta página para todas as diferentes variações de 'gatos' que correspondem.

Você também pode resolver isso usando condicionais , mas eles não são suportados no tipo javascript do regex.

Aurimas
fonte
3
Muito feio. Deve haver uma maneira melhor.
james.garriss
Você poderia torná-lo mais legível na sintaxe JS (embora a técnica funcione em outras linguagens) com:new RegExp('cats'.split('').join('(?:\n\s*)?'))
brianary 01 de
7

Embora a resposta aceita seja tecnicamente correta, uma abordagem mais prática, se possível, é apenas retirar os espaços em branco da expressão regular e da string de pesquisa.

Se você quiser pesquisar "meus gatos", em vez de:

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

Apenas faça:

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

Aviso: você não pode automatizar isso na expressão regular apenas substituindo todos os espaços por strings vazias porque eles podem ocorrer em uma negação ou tornar sua expressão regular inválida.

Konrad Höffner
fonte
5

Você poderia colocar \s*entre cada caractere em sua string de pesquisa, então se você estivesse procurando por um gato, você usariac\s*a\s*t\s*s\s*s

É longo, mas você pode construir a string dinamicamente, é claro.

Você pode vê-lo funcionando aqui: http://www.rubular.com/r/zzWwvppSpE

Kludge
fonte
3

Se você só deseja permitir espaços, então

\bc *a *t *s\b

deve fazer isso. Para permitir também guias, use

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

Remova as \bâncoras se também quiser encontrar catspalavras como bobcatsou catsup.

Tim Pietzcker
fonte
1

Esta abordagem pode ser usada para automatizar isso (a solução exemplar a seguir está em python, embora obviamente possa ser transferida para qualquer linguagem):

você pode remover o espaço em branco de antemão E salvar as posições dos caracteres que não são de espaço em branco para que possa usá-los posteriormente para descobrir as posições de limite da string correspondentes na string original, como a seguir:

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'

Se você quiser ir mais longe, pode construir o objeto de correspondência e retorná-lo em vez disso, portanto, o uso deste auxiliar será mais útil.

E o desempenho desta função também pode ser otimizado, este exemplo é apenas para mostrar o caminho para uma solução.

Prumo
fonte