Regex para string entre aspas e citações de escape

Como faço para obter a substring " It's big \"problem " usando uma expressão regular?

 s = ' function(){ return " It\'s big \"problem "; }'; 

 /"(?:[^"\\]|\\.)*"/ 

Trabalha no Regex Coach e no PCRE Workbench.

Exemplo de teste em JavaScript:

  var s = ' function(){ return " Is big \\"problem\\", \\no? "; }'; var m = s.match(/"(?:[^"\\]|\\.)*"/); if (m != null) alert(m); 

Este vem do nanorc.sample disponível em muitas distribuições linux. É usado para destaque de syntax de cadeias de estilo C

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

Conforme fornecido pelo ePharaoh, a resposta é

 /"([^"\\]*(\\.[^"\\]*)*)"/ 

Para que o acima se aplique a cadeias simples ou duplas, use

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

Alternando o \" e o . Passa sobre aspas escapadas enquanto o quantificador lento *? Garante que você não passe do final da string citada. Funciona com classs do .NET Framework RE

A maioria das soluções fornecidas aqui usa caminhos alternativos de repetição, ou seja, (A | B) *.

Você pode encontrar estouros de pilha em grandes inputs, pois algum compilador de padrões implementa isso usando recursion.

Java, por exemplo: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993

Algo parecido com isto: "(?:[^"\\]*(?:\\.)?)*" , Ou o fornecido por Guy Bedford reduzirá a quantidade de etapas de análise, evitando a maioria dos estouros de pilha.

 /"(?:[^"\\]++|\\.)*+"/ 

Retirado diretamente do man perlre em um sistema Linux com o Perl 5.22.0 instalado. Como uma otimização, esse regex usa a forma ‘posessive’ de ambos, + e * para evitar o retrocesso, pois é conhecido de antemão que uma string sem uma cota de fechamento não corresponderia em nenhum caso.

Este funciona perfeitamente no PCRE e não cai no StackOverflow.

 "(.*?[^\\])??((\\\\)+)?+" 

Explicação:

  1. Cada string entre aspas começa com Char: " ;
  2. Pode conter qualquer número de qualquer caractere:. {Lazy match}; terminando com caractere não escape [^\\] ;
  3. Statement (2) é Lazy (!) Opcional porque string pode estar vazia (“”). Então: (.*?[^\\])??
  4. Finalmente, cada string entre aspas termina com Char ( " ), mas pode ser precedida com pares pares de sinais de escape (\\\\)+ ; e é Greedy (!) Opcional: ((\\\\)+)?+ {Greedy matching}, a cadeia de bacause pode estar vazia ou sem terminar os pares!
 /(["\']).*?(?< !\\)(\\\\)*\1/is 

deve funcionar com qualquer string entre aspas

aqui é um que trabalha com “e” e você adiciona outros facilmente no início.

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

ele usa a referência de referência (\ 1) para combinar exatamente o que está no primeiro grupo (“ou”).

http://www.regular-expressions.info/backref.html

É preciso lembrar que os regexps não são uma bala de prata para tudo que é string-y. Algumas coisas são mais simples de fazer com um cursor e linear, manual, buscando. Um CFL faria o truque muito trivialmente, mas não há muitas implementações de CFL (afaik).

Uma versão mais abrangente do https://stackoverflow.com/a/10786066/1794894

 /"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/ 

Esta versão também contém

  1. Comprimento mínimo de cotação de 50
  2. Tipo extra de cotações (abrir e fechar )

Brincou na regexpal e acabou com esta regex: (Não me pergunte como funciona, eu mal entendo mesmo que eu escrevi isso lol)

 "(([^"\\]?(\\\\)?)|(\\")+)+" 

Se for pesquisado desde o início, talvez isso funcione?

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

Uma opção que não foi tocada antes é:

  1. Inverta a corda.
  2. Execute a correspondência na string invertida.
  3. Reverta novamente as strings correspondentes.

Isso tem a vantagem adicional de poder corresponder corretamente as tags abertas com escape.

Vamos dizer que você teve a seguinte string; String \"this "should" NOT match\" and "this \"should\" match" Aqui, \"this "should" NOT match\" não deve ser correspondido e "should" deveria ser. Além disso, this \"should\" match deve ser correspondida e \"should\" .

Primeiro um exemplo.

 // The input string. const myString = 'String \\"this "should" NOT match\\" and "this \\"should\\" match"'; // The RegExp. const regExp = new RegExp( // Match close '([\'"])(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))' + '((?:' + // Match escaped close quote '(?:\\1(?=(?:[\\\\]{2})*[\\\\](?![\\\\])))|' + // Match everything thats not the close quote '(?:(?!\\1).)' + '){0,})' + // Match open '(\\1)(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))', 'g' ); // Reverse the matched strings. matches = myString // Reverse the string. .split('').reverse().join('') // '"hctam "\dluohs"\ siht" dna "\hctam TON "dluohs" siht"\ gnirtS' // Match the quoted .match(regExp) // ['"hctam "\dluohs"\ siht"', '"dluohs"'] // Reverse the matches .map(x => x.split('').reverse().join('')) // ['"this \"should\" match"', '"should"'] // Re order the matches .reverse(); // ['"should"', '"this \"should\" match"'] 

Ok, agora para explicar o RegExp. Este é o regexp pode ser facilmente dividido em três partes. Do seguinte modo:

 # Part 1 (['"]) # Match a closing quotation mark " or ' (?! # As long as it's not followed by (?:[\\]{2})* # A pair of escape characters [\\] # and a single escape (?![\\]) # As long as that's not followed by an escape ) # Part 2 ((?: # Match inside the quotes (?: # Match option 1: \1 # Match the closing quote (?= # As long as it's followed by (?:\\\\)* # A pair of escape characters \\ # (?![\\]) # As long as that's not followed by an escape ) # and a single escape )| # OR (?: # Match option 2: (?!\1). # Any character that isn't the closing quote ) )*) # Match the group 0 or more times # Part 3 (\1) # Match an open quotation mark that is the same as the closing one (?! # As long as it's not followed by (?:[\\]{2})* # A pair of escape characters [\\] # and a single escape (?![\\]) # As long as that's not followed by an escape ) 

Isto é provavelmente muito mais claro em forma de imagem: gerado usando o Regulex de Jex

Image on github (Visualizador de Expressões Regulares em JavaScript.) Desculpe, eu não tenho uma reputação alta o suficiente para include imagens, então, é apenas um link por enquanto.

Aqui está uma essência de uma function de exemplo usando este conceito que é um pouco mais avançado: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js

Eu enfrentei um problema semelhante ao tentar remover strings citadas que podem interferir na análise de alguns arquivos.

Acabei com uma solução de duas etapas que supera qualquer regex complicado que você possa criar:

  line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful 

Mais fácil de ler e provavelmente mais eficiente.