Como você encontra "It" em uma string que contém apenas "Is"? Eu o corrigi, mas não sei quais convenções de aspas simples / de escape se aplicam no idioma que você está usando.
Na verdade, olhando as datas, vejo que a outra pergunta é uma duplicata desta. De qualquer maneira, verifique minha resposta .
Ridgerunner
@ridgerunner: Estou votando para fechar isso como você sugeriu. É verdade que outra pergunta é mais recente, mas também é muito melhor (graças principalmente à sua resposta).
Alan Moore
Respostas:
158
/"(?:[^"\\]|\\.)*"/
Trabalha no The 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);
Faz sentido. Inglês simples: duas aspas envolvendo zero ou mais de "qualquer caractere que não seja uma citação ou uma barra invertida" ou "uma barra invertida seguida por qualquer caractere". Eu não posso acreditar que eu não acho que para fazer isso ...
Ajedi32
7
Eu vou me responder. =) (?:...)é um grupo passivo ou não captador. Isso significa que não pode ser referenciado posteriormente mais tarde.
Magras
depois de pesquisar bastante e testar bastante, essa é a única e real solução que encontrei para esse problema comum. Obrigado!
Cancerbero
9
obrigado por isso. eu queria para combinar aspas simples, bem assim i acabou adaptando-a isto:/(["'])(?:[^\1\\]|\\.)*?\1/
c.nanorc foi o primeiro lugar que eu fui. Não foi possível obtê-lo para o trabalho como parte de um literal de cadeia C até duas vezes escapando tudo como esta" \"(\\\\.|[^\\\"])*\" "
hellork
Isso funciona com as funções egrep e re_comp / re_exec da libc.
Fk0
19
Conforme fornecido pelo ePharaoh, a resposta é
/"([^"\\]*(\\.[^"\\]*)*)"/
Para que o descrito acima se aplique a cadeias simples ou duplas, use
Este é o único conjunto que funcionou para mim com uma única e grande seqüência de caracteres citada de 1,5 KB contendo 99 escapes. Todas as outras expressões nesta página foram interrompidas no meu editor de texto com um erro de estouro. Embora a maioria aqui funcione no navegador, apenas algo a ter em mente. Fiddle: jsfiddle.net/aow20y0L
Beejor
3
Veja a resposta de @ MarcAndrePoulin abaixo para explicação.
shaunc
10
A maioria das soluções fornecidas aqui usa caminhos alternativos de repetição, como (A | B) *.
Você pode encontrar estouros de pilha em entradas grandes, pois algum compilador de padrões implementa isso usando recursão.
Alternando entre \"e as .passagens sobre aspas escapadas, enquanto o quantificador lento *?garante que você não ultrapasse o final da sequência de caracteres citada. Funciona com classes do .NET Framework RE
Retirado diretamente de man perlreum sistema Linux com o Perl 5.22.0 instalado. Como uma otimização, esse regex usa a forma 'posessiva' de ambos +e *para impedir o retorno, pois é sabido de antemão que uma sequência sem uma citação de fechamento não corresponderia em nenhum caso.
Agradável, mas flexível demais para a solicitação (corresponderá aspas simples ...). E pode ser simplificado para /".*?(?<!\)"/, a menos que eu perca alguma coisa. Ah, e algumas linguagens (por exemplo, JavaScript) infelizmente não entendem expressões negativas.
PhiLho
1
@ PhiLho, apenas o uso de um único (? <! \\) falharia nas barras invertidas escapadas no final da string. Porém, é verdade sobre os atrasos no JavaScript.
Markus Jarderot
4
Este funciona perfeitamente no PCRE e não cai com o StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Explicação:
Cada string começa com Char: ";
Pode conter qualquer número de caracteres: .*?{Lazy match}; terminando com caractere sem escape [^\\];
A instrução (2) é preguiçosa (!) Opcional porque a cadeia pode estar vazia (""). Assim:(.*?[^\\])??
Finalmente, toda string citada termina com Char ( "), mas pode ser precedida de um número par de pares de sinais de escape (\\\\)+; e é Greedy (!) opcional: ((\\\\)+)?+{Correspondência Greedy}, a seqüência de caracteres pode estar vazia ou sem pares finais!
Esta é uma solução muito boa, mas [^\1]deve ser substituída por, .porque não existe uma referência anti-retorno e isso não importa. a primeira condição sempre corresponderá antes que algo ruim possa acontecer.
Seph Reed
@SephReed - substituindo [^\1]com .efetivamente mudar esta regex para ("|').*?\1e em seguida, ele iria corresponder "foo\"no "foo \" bar". Dito isto, [^\1]é realmente difícil trabalhar. @ Mathiashansen - Você é melhor fora com o complicado e caro (?!\1).(para o todo regex, com alguma limpeza eficiência, seria (["'])(?:\\.|(?!\1).)*+\1A. +É opcional se o seu motor não apoiá-lo.
Adam Katz
2
Uma opção que não foi abordada antes é:
Inverta a string.
Faça a correspondência na sequência invertida.
Reverta as seqüências correspondentes.
Isso tem o bônus adicional de poder corresponder corretamente as tags abertas com escape.
Digamos que você tenha a seguinte string; String \"this "should" NOT match\" and "this \"should\" match"
Aqui, \"this "should" NOT match\"não deve ser correspondido e "should"deve ser. Além disso this \"should\" match, isso deve corresponder e \"should\"não.
Primeiro um exemplo.
// The input string.const myString ='String \\"this "should" NOT match\\" and "this \\"should\\" match"';// The RegExp.const regExp =newRegExp(// 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)
Provavelmente, isso é muito mais claro na forma de imagem: gerado usando o Regulex de Jex
É preciso lembrar que os regexps não são uma bala de prata para tudo que é y. Algumas coisas são mais simples de fazer com um cursor e linear, manual, buscando. Uma CFL faria o truque de maneira bastante trivial, mas não há muitas implementações de CFL (afaik).
Eu enfrentei um problema semelhante ao tentar remover as seqüências de caracteres citadas que podem interferir na análise de alguns arquivos.
Acabei com uma solução em 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
Se o seu IDE for IntelliJ Idea, você poderá esquecer todas essas dores de cabeça e armazenar sua regex em uma variável String e, ao copiar e colar dentro da aspas duplas, ela mudará automaticamente para um formato aceitável para regex.
exemplo em Java:
String s ="\"en_usa\":[^\\,\\}]+";
agora você pode usar essa variável no seu regexp ou em qualquer outro lugar.
Respostas:
Trabalha no The Regex Coach e no PCRE Workbench.
Exemplo de teste em JavaScript:
fonte
(?:...)
é um grupo passivo ou não captador. Isso significa que não pode ser referenciado posteriormente mais tarde./(["'])(?:[^\1\\]|\\.)*?\1/
var s = ' my \\"new\\" string and \"this should be matched\"';
, essa abordagem levará a resultados inesperados.Este é um exemplo de nanorc.sample disponível em muitas distribuições linux. É usado para destacar a sintaxe de seqüências de caracteres de estilo C
fonte
var s = ' my \\"new\\" string and \"this should be matched\"';
, essa abordagem levará a resultados inesperados." \"(\\\\.|[^\\\"])*\" "
Conforme fornecido pelo ePharaoh, a resposta é
Para que o descrito acima se aplique a cadeias simples ou duplas, use
fonte
A maioria das soluções fornecidas aqui usa caminhos alternativos de repetição, como (A | B) *.
Você pode encontrar estouros de pilha em entradas grandes, pois algum compilador de padrões implementa isso usando recursão.
Java, por exemplo: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
Algo assim:
"(?:[^"\\]*(?:\\.)?)*"
ou o fornecido por Guy Bedford reduzirá a quantidade de etapas de análise, evitando a maioria dos estouros de pilha.fonte
Alternando entre
\"
e as.
passagens sobre aspas escapadas, enquanto o quantificador lento*?
garante que você não ultrapasse o final da sequência de caracteres citada. Funciona com classes do .NET Framework REfonte
"\\"
var s = ' my \\"new\\" string and \"this should be matched\"';
/"(?:(?:\\"|[^"])*)"/g
isso deve corrigirRetirado diretamente de
man perlre
um sistema Linux com o Perl 5.22.0 instalado. Como uma otimização, esse regex usa a forma 'posessiva' de ambos+
e*
para impedir o retorno, pois é sabido de antemão que uma sequência sem uma citação de fechamento não corresponderia em nenhum caso.fonte
deve funcionar com qualquer string entre aspas
fonte
Este funciona perfeitamente no PCRE e não cai com o StackOverflow.
Explicação:
"
;.*?
{Lazy match}; terminando com caractere sem escape[^\\]
;(.*?[^\\])??
"
), mas pode ser precedida de um número par de pares de sinais de escape(\\\\)+
; e é Greedy (!) opcional:((\\\\)+)?+
{Correspondência Greedy}, a seqüência de caracteres pode estar vazia ou sem pares finais!fonte
"(.*?[^\\])?(\\\\)*"
aqui está um que funciona com "e" e você adiciona outros facilmente no início.
ele usa a referência anterior (\ 1) corresponde exatamente ao que está no primeiro grupo ("ou ').
http://www.regular-expressions.info/backref.html
fonte
[^\1]
deve ser substituída por,.
porque não existe uma referência anti-retorno e isso não importa. a primeira condição sempre corresponderá antes que algo ruim possa acontecer.[^\1]
com.
efetivamente mudar esta regex para("|').*?\1
e em seguida, ele iria corresponder"foo\"
no"foo \" bar"
. Dito isto,[^\1]
é realmente difícil trabalhar. @ Mathiashansen - Você é melhor fora com o complicado e caro(?!\1).
(para o todo regex, com alguma limpeza eficiência, seria(["'])(?:\\.|(?!\1).)*+\1
A.+
É opcional se o seu motor não apoiá-lo.Uma opção que não foi abordada antes é:
Isso tem o bônus adicional de poder corresponder corretamente as tags abertas com escape.
Digamos que você tenha a seguinte string;
String \"this "should" NOT match\" and "this \"should\" match"
Aqui,\"this "should" NOT match\"
não deve ser correspondido e"should"
deve ser. Além dissothis \"should\" match
, isso deve corresponder e\"should\"
não.Primeiro um exemplo.
Ok, agora para explicar o RegExp. Este é o regexp pode ser facilmente dividido em três partes. Do seguinte modo:
Provavelmente, isso é muito mais claro na forma de imagem: gerado usando o Regulex de Jex
Imagem no github (JavaScript Regular Expression Visualizer.) Desculpe, não tenho uma reputação suficientemente alta para incluir imagens; portanto, é apenas um link no momento.
Aqui está um exemplo de uma função de exemplo usando esse conceito um pouco mais avançado: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
fonte
É preciso lembrar que os regexps não são uma bala de prata para tudo que é y. Algumas coisas são mais simples de fazer com um cursor e linear, manual, buscando. Uma CFL faria o truque de maneira bastante trivial, mas não há muitas implementações de CFL (afaik).
fonte
Uma versão mais extensa do https://stackoverflow.com/a/10786066/1794894
Esta versão também contém
“
e fechar”
)fonte
Mexi no regexpal e acabei com este regex: (Não me pergunte como funciona, eu mal entendo mesmo que eu o tenha escrito lol)
fonte
Se for pesquisado desde o início, talvez isso possa funcionar?
fonte
Eu enfrentei um problema semelhante ao tentar remover as seqüências de caracteres citadas que podem interferir na análise de alguns arquivos.
Acabei com uma solução em duas etapas que supera qualquer regex complicado que você possa criar:
Mais fácil de ler e provavelmente mais eficiente.
fonte
Se o seu IDE for IntelliJ Idea, você poderá esquecer todas essas dores de cabeça e armazenar sua regex em uma variável String e, ao copiar e colar dentro da aspas duplas, ela mudará automaticamente para um formato aceitável para regex.
exemplo em Java:
agora você pode usar essa variável no seu regexp ou em qualquer outro lugar.
fonte