17 de dez de 2008 17:19 do Graeme Perrow

Como posso combinar uma string delimitada por aspas com uma regex?

Se estou tentando combinar uma string delimitada por aspas com uma expressão regular, qual das opções a seguir é "melhor" (onde "melhor" significa mais eficiente e menos propenso a fazer algo inesperado):

/"[^"]+"/ # match quote, then everything that's not a quote, then a quote

ou

/".+?"/   # match quote, then *anything* (non-greedy), then a quote

Suponha para esta pergunta que cadeias vazias (ou seja, "") não sejam um problema. Parece-me (sem regex novato, mas certamente nenhum especialista) que estes serão equivalentes.

Atualizar: Após a reflexão, acho que mudar o+ caracteres para* manipulará as cadeias vazias corretamente de qualquer maneira.

questionAnswers (0)

21 de jun de 2013 09:17 do nico

mas lida com aspas escapadas e também com barras invertidas escapadas (as barras invertidas seguidas por uma citação não são um problema)

/(["'])((\\{2})*|(.*?[^\\](\\{2})*))\1/

Exemplos:
  "Olá Mundo" fósforos"Olá Mundo"
  "Olá Mundo" fósforos"Olá\\"

17 de dez de 2008 17:37 do 1,059

Eu sugeriria:

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

Mas apenas porque ele lida com caracteres de citação escapados e permite que o 'e "sejam o caractere de citação. Eu também sugeriria examinar este artigo que aborda esse problema em profundidade:

http://blog.stevenlevithan.com/archives/match-quoted-string

No entanto, a menos que você tenha um problema sério de desempenho ou não tenha certeza de cotações incorporadas, siga o mais simples e legível:

/".*?"/

Devo admitir que padrões não gananciosos não são a expressão regular básica do estilo Unix, mas estão se tornando bastante comuns. Ainda não estou acostumado a agrupar operadores como (?: Coisas).

17 de dez de 2008 17:27 do Tomalak

xecução sobre seqüências longas), eu poderia imaginar que

"[^"]*"

é mais rápido que

".*?"

porque o último faria uma verificação adicional para cada etapa: espreitar o próximo personagem. O primeiro seria capaz de rolar sem pensar sobre a corda.

Como eu disse, em cenários do mundo real isso dificilmente seria perceptível. Portanto, eu iria com o número dois (se meu sabor atual de regex o suportar, ou seja), porque é muito mais legível. Caso contrário, com o número um, é claro.

17 de dez de 2008 16:40 do Paul Tomblin

*?" até hoje, e eu uso expressões regulares há mais de 20 anos, eu votaria a favor do primeiro. Certamente deixa claro o que você está tentando fazer - você está tentando corresponder uma string que não inclui aspas.

17 de dez de 2008 16:27 do PEZ

já que é muito mais fácil ler. Mas eu ainda gostaria de combinar cadeias de caracteres vazias para usar:

/".*?"/
29 de dez de 2008 18:04 do 423

o caractere de limite (aspas duplas, no seu exemplo) está presente em outro local da entrada.

Seu exemplo # 1:

/"[^"]+"/ # match quote, then everything that's not a quote, then a quote

corresponde apenas ao menor par de aspas correspondentes - excelente e, na maioria das vezes, é tudo o que você precisa. No entanto, se você tiver aspas aninhadas e estiver interessado no maior par de aspas correspondentes (ou em todas as aspas correspondentes), estará em uma situação muito mais complicada.

Felizmente Damian Conway está pronto para o resgate:Texto :: Balanceado está disponível para você, se você achar que há várias aspas correspondentes. Ele também tem a virtude de corresponder a outra pontuação emparelhada, por exemplo parênteses.

17 de dez de 2008 16:38 do 28.1k

porque falha mais rápido quando o encerramento" está desaparecido. O primeiro vai voltar atrás sobre a corda, uma operação potencialmente cara. Uma regexp alternativa, se você estiver usando o perl 5.10, seria/"[^"]++"/. Ele transmite o mesmo significado que a versão 1, mas é tão rápido quanto a versão dois.

18 de dez de 2008 10:45 do 16.9k

porque o número dois é uma prática ruim. Considere que o desenvolvedor que vem depois de você deseja corresponder as strings que são seguidas por um ponto de exclamação. Ele deveria usar:

"[^"]*"!

ou:

".*?"!

A diferença aparece quando você tem o assunto:

"one" "two"!

A primeira regex corresponde:

"two"!

enquanto o segundo regex corresponde:

"one" "two"!

Seja sempre o mais específico possível. Use a classe de caracteres negados quando puder.

Outra diferença é que [^ "] * pode se estender por linhas, enquanto. * Não, a menos que você use o modo de linha única. [^" \ N] * também exclui as quebras de linha.

Quanto ao retorno, o segundo regex retorna para cada caractere em cada sequência que ele corresponder. Se a cotação de fechamento estiver ausente, as duas expressões regulares retornarão ao longo de todo o arquivo. Somente a ordem na qual o retorno é diferente. Assim, em teoria, o primeiro regex é mais rápido. Na prática, você não notará a diferença.

17 de dez de 2008 16:32 do Douglas Leeder

O primeiro pode ser mais eficiente?

Search for double-quote
add double-quote to group
for each char:
    if double-quote:
        break
    add to group
add double-quote to group

Vs algo um pouco mais complicado envolvendo back-tracking?

yourAnswerToTheQuestion