Come ottengo la sottostringa " It's big \"problem "
utilizzando un'espressione regolare?
s = ' function(){ return " It\'s big \"problem "; }';
Come ottengo la sottostringa " It's big \"problem "
utilizzando un'espressione regolare?
s = ' function(){ return " It\'s big \"problem "; }';
Risposte:
/"(?:[^"\\]|\\.)*"/
Funziona in The Regex Coach e PCRE Workbench.
Esempio di test in JavaScript:
var s = ' function(){ return " Is big \\"problem\\", \\no? "; }';
var m = s.match(/"(?:[^"\\]|\\.)*"/);
if (m != null)
alert(m);
(?:...)
è un gruppo passivo o non di acquisizione. Significa che non è possibile fare riferimento indietro in seguito.
/(["'])(?:[^\1\\]|\\.)*?\1/
var s = ' my \\"new\\" string and \"this should be matched\"';
, questo approccio porterà a risultati inaspettati.
Questo proviene da nanorc.sample disponibile in molte distribuzioni Linux. Viene utilizzato per evidenziare la sintassi delle stringhe in stile C.
\"(\\.|[^\"])*\"
var s = ' my \\"new\\" string and \"this should be matched\"';
, questo approccio porterà a risultati inaspettati.
" \"(\\\\.|[^\\\"])*\" "
Come fornito da ePharaoh, la risposta è
/"([^"\\]*(\\.[^"\\]*)*)"/
Per fare in modo che quanto sopra si applichi a stringhe tra virgolette singole o doppie, utilizzare
/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
La maggior parte delle soluzioni fornite qui utilizza percorsi di ripetizione alternativi, ad esempio (A | B) *.
È possibile riscontrare overflow dello stack su input di grandi dimensioni poiché alcuni compilatori di pattern lo implementano utilizzando la ricorsione.
Java ad esempio: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
Qualcosa del genere:
"(?:[^"\\]*(?:\\.)?)*"
o quello fornito da Guy Bedford ridurrà la quantità di passaggi di analisi evitando la maggior parte degli overflow dello stack.
/"(?:[^"\\]++|\\.)*+"/
Preso direttamente da man perlre
un sistema Linux con Perl 5.22.0 installato. Come ottimizzazione, questa regex utilizza la forma "positiva" di entrambi +
e *
per impedire il backtracking, poiché è noto in anticipo che una stringa senza virgolette di chiusura non corrisponderebbe in ogni caso.
/(["\']).*?(?<!\\)(\\\\)*\1/is
dovrebbe funzionare con qualsiasi stringa tra virgolette
Questo funziona perfettamente su PCRE e non cade con StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Spiegazione:
"
;.*?
{Lazy match}; che termina con un carattere non di escape[^\\]
;(.*?[^\\])??
"
), ma può essere preceduta da un numero pari di coppie di segni di escape (\\\\)+
; ed è Greedy (!) opzionale: ((\\\\)+)?+
{Greedy matching}, perché la stringa può essere vuota o senza coppie finali!"(.*?[^\\])?(\\\\)*"
eccone uno che funziona con entrambi "e 'e ne aggiungi facilmente altri all'inizio.
( "| ')? (: \\\ 1 | [^ \ 1])? * \ 1
usa il backreference (\ 1) che corrisponde esattamente a ciò che è nel primo gruppo ("o ').
[^\1]
dovrebbe essere sostituita con .
perché non esiste un anti-back-reference, e comunque non ha importanza. la prima condizione corrisponderà sempre prima che possa accadere qualcosa di brutto.
[^\1]
con .
cambierebbe in modo efficace questa regex per ("|').*?\1
e poi sarebbe partita "foo\"
in "foo \" bar"
. Detto questo, mettersi [^\1]
al lavoro è davvero difficile. @ Mathiashansen - Stai meglio con quelli ingombranti e costosi (?!\1).
(quindi l'intera regex, con un po 'di pulizia dell'efficienza, sarebbe (["'])(?:\\.|(?!\1).)*+\1
. +
È opzionale se il tuo motore non lo supporta.
Un'opzione che non è stata toccata prima è:
Questo ha il vantaggio aggiuntivo di poter abbinare correttamente i tag aperti con escape.
Diciamo che hai avuto la seguente stringa; String \"this "should" NOT match\" and "this \"should\" match"
Qui, \"this "should" NOT match\"
non dovrebbe essere abbinato e "should"
dovrebbe essere. Inoltre this \"should\" match
dovrebbe essere abbinato e \"should\"
non dovrebbe.
Prima un esempio.
// 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"']
Va bene, ora per spiegare la RegExp. Questa è la regexp che può essere facilmente suddivisa in tre parti. Come segue:
# 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
)
Questo è probabilmente molto più chiaro nella forma dell'immagine: generata usando Regulex di Jex
Immagine su github (JavaScript Regular Expression Visualizer.) Spiacente, non ho una reputazione abbastanza alta per includere immagini, quindi per ora è solo un collegamento.
Ecco una sintesi di una funzione di esempio che utilizza questo concetto che è un po 'più avanzato: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
Bisogna ricordare che le espressioni regolari non sono un proiettile d'argento per tutto ciò che è stringa-y. Alcune cose sono più semplici da fare con un cursore e una ricerca lineare, manuale. Una CFL farebbe il trucco abbastanza banalmente, ma non ci sono molte implementazioni CFL (afaik).
Una versione più estesa di https://stackoverflow.com/a/10786066/1794894
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
Questa versione contiene anche
“
e chiusura ”
)Se viene cercato dall'inizio, forse può funzionare?
\"((\\\")|[^\\])*\"
Ho riscontrato un problema simile cercando di rimuovere le stringhe tra virgolette che potrebbero interferire con l'analisi di alcuni file.
Ho finito con una soluzione in due passaggi che batte qualsiasi regex contorto che puoi trovare:
line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle
line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful
Più facile da leggere e probabilmente più efficiente.
Se il tuo IDE è IntelliJ Idea, puoi dimenticare tutti questi mal di testa e memorizzare la tua regex in una variabile String e mentre la copi e incolli all'interno delle virgolette, cambierà automaticamente in un formato accettabile di regex.
esempio in Java:
String s = "\"en_usa\":[^\\,\\}]+";
ora puoi usare questa variabile nella tua regexp o ovunque.