Comment puis-je obtenir la sous-chaîne " It's big \"problem "
en utilisant une expression régulière ?
s = ' function(){ return " It\'s big \"problem "; }';
Comment puis-je obtenir la sous-chaîne " It's big \"problem "
en utilisant une expression régulière ?
s = ' function(){ return " It\'s big \"problem "; }';
La plupart des solutions proposées ici utilisent des chemins de répétition alternatifs, c'est-à-dire (A|B)*.
Vous pouvez rencontrer des débordements de pile sur des entrées importantes, car certains compilateurs de motifs les mettent en œuvre en utilisant la récursion.
Java, par exemple : http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
Quelque chose comme ça : "(?:[^"\\]*(?:\\.)?)*"
ou celui fourni par Guy Bedford réduira le nombre d'étapes d'analyse syntaxique en évitant la plupart des débordements de pile.
/"(?:[^"\\]++|\\.)*+"/
Tiré directement de man perlre
sur un système Linux avec Perl 5.22.0 installé. Par souci d'optimisation, cette regex utilise la forme "posessive" des deux éléments suivants +
y *
pour éviter le retour en arrière, car on sait à l'avance qu'une chaîne sans guillemet fermant ne correspondrait pas dans tous les cas.
Celui-ci fonctionne parfaitement sur PCRE et ne tombe pas avec StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Explication :
"
;.*?
{Lazy match} ; se terminant par un caractère non échappatoire [^\\]
;(.*?[^\\])??
"
), mais il peut être précédé d'un nombre pair de paires de signes d'échappement (\\\\)+
; et il est Greedy( !) facultatif : ((\\\\)+)?+
{Concordance avide}, car la chaîne peut être vide ou sans paires finales !Une option qui n'a pas été abordée auparavant est la suivante :
Cette méthode présente l'avantage supplémentaire de pouvoir faire correspondre correctement les balises ouvertes échappées.
Disons que vous avez la chaîne suivante ; String \"this "should" NOT match\" and "this \"should\" match"
Ici, \"this "should" NOT match\"
ne doivent pas être appariés et "should"
devrait être. En plus de cela this \"should\" match
doivent être appariés et \"should\"
ne devrait pas.
D'abord un exemple.
// 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, maintenant expliquons le RegExp. L'expression géographique peut être facilement divisée en trois parties. Comme suit :
# 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
)
C'est probablement beaucoup plus clair sous forme d'image : généré à l'aide de Regulex de Jex
Image sur github (JavaScript Regular Expression Visualizer.) Désolé, je n'ai pas une réputation assez élevée pour inclure des images, donc, c'est juste un lien pour le moment.
Voici l'essentiel d'un exemple de fonction utilisant ce concept, un peu plus avancé : https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.