Regex;backreferencing um personagem que NÃO foi correspondido em um conjunto de caracteres

StackOverflow https://stackoverflow.com//questions/9718393

Pergunta

Eu quero construir uma regex, o que corresponde a ' ou " e corresponde, em seguida, outros personagens, terminando quando um ' ou um " respectivamente for correspondido, dependendo do que foi encontrado logo no início.Portanto, esse problema parece simples o suficiente para resolver com o uso de um retrorreferência no final;aqui estão algumas regex código abaixo (é em Java, então a mente extra de escape de caracteres, tais como o \ antes de o "):

private static String seekerTwo = "(['\"])([a-zA-Z])([a-zA-Z0-9():;/`\\=\\.\\,\\- ]+)(\\1)";

Esse código vai conseguir lidar com as coisas tais como:

"hello my name is bob"
'i live in bethnal green'

O problema vem quando eu tiver uma String assim:

"hello this seat 'may be taken' already"

Usando o acima de regex, ele vai falhar na primeira parte, após encontrar ' em seguida, ele iria continuar e combinar com êxito 'may be taken'...mas este é manifestamente insuficiente, eu preciso de toda a Cadeia de caracteres a ser correspondido.

O que eu estou pensando, é que eu preciso de uma maneira de ignorar o tipo de aspas, o que NÃO foi correspondido no primeiro grupo, incluindo-a como um caractere no conjunto do 3º grupo.No entanto, não conheço nenhuma maneira de fazer isso.Existe algum tipo de sneaky NÃO retrorreferência função ou algo assim?Algo que eu possa usar para fazer referência a que o personagem do 1º grupo que NÃO foi correspondido??Ou, caso contrário, algum tipo de solução para a minha situação?

Foi útil?

Solução

Isso pode ser feito usando negativo procura afirmações.A seguinte solução, mesmo leva em conta que você pode escapar de uma citação dentro de uma string:

(["'])(?:\\.|(?!\1).)*\1

Explicação:

(["'])    # Match and remember a quote.
(?:       # Either match...
 \\.      # an escaped character
|         # or
 (?!\1)   # (unless that character is identical to the quote character in \1)
 .        # any character
)*        # any number of times.
\1        # Match the corresponding quote.

Isso corresponde corretamente "hello this seat 'may be taken' already" ou "hello this seat \"may be taken\" already".

Em Java, com todas as barras invertidas:

Pattern regex = Pattern.compile(
    "([\"'])   # Match and remember a quote.\n" +
    "(?:       # Either match...\n" +
    " \\\\.    # an escaped character\n" +
    "|         # or\n" +
    " (?!\\1)  # (unless that character is identical to the matched quote char)\n" +
    " .        # any character\n" +
    ")*        # any number of times.\n" +
    "\\1       # Match the corresponding quote", 
    Pattern.COMMENTS);

Outras dicas

Tim solução funciona muito bem se você pode usar lookaround (Java que suporta).Mas se você deve encontrar a si mesmo usando uma linguagem ou ferramenta que não suporta lookaround, você pode simplesmente combinar ambos os casos (duas seqüências de caracteres entre aspas e único seqüências de caracteres entre aspas) separadamente:

"(\\"|[^"])*"|'(\\'|[^'])*'

corresponde a cada caso separadamente, mas retorna um caso como o de toda a partida


No ENTANTO

Ambos os casos podem cair pelo menos uma eventualidade.Se você não olhar de perto, você pode pensar que não deve ser dois partidas neste trecho:

Ele virou-se para chegar em sua bicicleta."Eu te vejo mais tarde, quando eu tenho feito com tudo isso", ele disse, olhando para trás por um momento, antes de iniciar sua viagem.Como ele entrou na rua, um dos carrinhos colidiu com Mike bicicleta."Oh, meu deus!", exclamou um espectador.

...mas não são três corresponde, e não dois:

"I'll see you later, when I'm done with all this"
's trolleys collided with Mike'
"Oh my!"

e este trecho contém apenas UM correspondência:

A luta ainda não tinha terminado, embora."Hey!" gritou Bob."O que você quer?" Eu retorqui."Eu odeio suas entranhas!" "Por que eu me importo?" "Porque eu amo você!" "Você faz?" Bob parou por um momento antes de sussurrar: "Não, eu não poderia amar você!"

você pode encontrar que um?:D

't over yet, though. "Hey!" yelled Bob. "What do you want?" I retorted. "I hate your guts!" "Why would I care?" "Because I love you!" "You do?" Bob paused for a moment before whispering "No, I couldn'

Eu recomendo (se você for para usar lookaround), que você considere a possibilidade de fazer algumas verificação extra (como um positivo de recuo para o espaço em branco ou similar, antes da primeira citação) para certificar-se de que você não coincidir com as coisas, como 's trolleys collided with Mike' - apesar de eu não colocar muito dinheiro em qualquer solução, sem um monte de teste primeiro.Adicionar (?<=\s|^) para o início de qualquer expressão de evitar os casos acima...i.e.:

(?<=\s|^)(["'])(?:\\.|(?!\1).)*\1                    #based on Tim's

ou

(?<=\s|^)("(\\"|[^"])*"|'(\\'|[^'])*')               #based on my alternative

Eu não tenho certeza de quão eficiente lookaround é comparados aos não-lookaround, assim que os dois acima pode ser equivalente, ou um pode ser mais eficiente do que o outro (?)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top