Comment trouvez-vous «C'est» dans une chaîne qui ne contient que «Est»? Je le réparerais pour vous, mais je ne sais pas quelles conventions de guillemet simple / d'échappement s'appliquent dans la langue que vous utilisez.
En fait, en regardant les dates, je vois que l'autre question est un double de celle-ci. De toute façon, assurez-vous de vérifier ma réponse .
ridgerunner
@ridgerunner: Je vote pour fermer ceci comme vous l'avez suggéré. C'est vrai qu'une autre question est plus récente, mais c'est aussi beaucoup mieux (grâce surtout à votre réponse).
Alan Moore
Réponses:
160
/"(?:[^"\\]|\\.)*"/
Fonctionne dans The Regex Coach et PCRE Workbench.
Exemple de test en JavaScript:
var s =' function(){ return " Is big \\"problem\\", \\no? "; }';var m = s.match(/"(?:[^"\\]|\\.)*"/);if(m !=null)
alert(m);
Logique. Anglais simple: deux guillemets entourant zéro ou plus de «tout caractère qui n'est pas une citation ou une barre oblique inverse» ou «une barre oblique inverse suivie de n'importe quel caractère». Je ne peux pas croire que je n'ai pas pensé à faire ça ...
Ajedi32
7
Je vais me répondre. =) (?:...)est un groupe passif ou non capturant. Cela signifie qu'il ne peut pas être référencé ultérieurement.
magras
après avoir beaucoup cherché et testé, c'est la vraie et seule solution que j'ai trouvée à ce problème courant. Merci!
cancerbero
10
Merci pour cela. Je voulais aussi faire correspondre des guillemets simples, alors j'ai fini par l'adapter à ceci:/(["'])(?:[^\1\\]|\\.)*?\1/
Celui-ci provient de nanorc.sample disponible dans de nombreuses distributions Linux. Il est utilisé pour la coloration syntaxique des chaînes de style C
c.nanorc était le premier endroit où je suis allé. Impossible de le faire fonctionner dans le cadre d'un littéral de chaîne C jusqu'à ce que tout double échappement comme celui-ci" \"(\\\\.|[^\\\"])*\" "
hellork
Cela fonctionne avec les fonctions egrep et re_comp / re_exec de la libc.
fk0
19
Comme fourni par ePharaoh, la réponse est
/"([^"\\]*(\\.[^"\\]*)*)"/
Pour appliquer ce qui précède aux chaînes entre guillemets simples ou doubles, utilisez
C'est le seul ensemble qui a fonctionné pour moi avec une seule grande chaîne citée de 1,5 Ko contenant 99 échappements. Toutes les autres expressions de cette page ont éclaté dans mon éditeur de texte avec une erreur de débordement. Bien que la plupart ici fonctionnent dans le navigateur, juste quelque chose à garder à l'esprit. Fiddle: jsfiddle.net/aow20y0L
Beejor
3
Voir la réponse de @ MarcAndrePoulin ci-dessous pour une explication.
shaunc
10
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 volumineuses car certains compilateurs de modèles implémentent cela en utilisant la récursivité.
Quelque chose comme ça:
"(?:[^"\\]*(?:\\.)?)*" ou celui fourni par Guy Bedford réduira le nombre d'étapes d'analyse en évitant la plupart des débordements de pile.
Alterner les \"et les .passes sur les guillemets échappés tandis que le quantificateur paresseux *?garantit que vous ne dépassez pas la fin de la chaîne entre guillemets. Fonctionne avec les classes .NET Framework RE
Tiré directement d' man perlreun système Linux avec Perl 5.22.0 installé. En guise d'optimisation, cette expression régulière utilise la forme «posessive» des deux +et *pour empêcher le retour en arrière, car il est connu à l'avance qu'une chaîne sans guillemets fermants ne correspondrait dans aucun cas.
Nice, mais trop flexible pour la demande (correspondra aux guillemets simples ...). Et peut être simplifié en /".*?(?<!\)"/ sauf si je manque quelque chose. Oh, et certains langages (par exemple JavaScript) ne comprennent hélas pas les expressions de regard négatif.
PhiLho
1
@PhiLho, l'utilisation d'un seul (? <! \\) échouerait sur les contre-obliques échappées à la fin de la chaîne. C'est vrai pour les look-behind en JavaScript.
Markus Jarderot
4
Celui-ci fonctionne parfaitement sur PCRE et ne tombe pas avec StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Explication:
Chaque chaîne entre guillemets commence par Char: ";
Il peut contenir n'importe quel nombre de caractères: .*?{Lazy match}; se terminant par un caractère non d'échappement[^\\] ;
L'instruction (2) est facultative Lazy (!) Car la chaîne peut être vide (""). Alors:(.*?[^\\])??
Enfin, chaque chaîne entre guillemets se termine par Char ( "), mais elle peut être précédée d'un nombre pair de paires de signes d'échappement (\\\\)+; et c'est Greedy (!) optionnel: ((\\\\)+)?+{Greedy matching}, la chaîne bacause peut être vide ou sans paires de fin!
c'est une très bonne solution, mais [^\1]devrait être remplacée par .car il n'y a pas d'anti-back-reference, et cela n'a pas d'importance de toute façon. la première condition correspondra toujours avant que quelque chose de mauvais puisse arriver.
Seph Reed
@SephReed - remplacement [^\1]avec .aurait pour effet de changer cette expression rationnelle ("|').*?\1et il correspondrait "foo\"à "foo \" bar". Cela dit, il [^\1]est difficile de se mettre au travail. @ Mathiashansen - Vous êtes mieux avec le peu maniable et cher (?!\1).(donc l'ensemble de la regex, avec un certain nettoyage d'efficacité, le serait (["'])(?:\\.|(?!\1).)*+\1. Le +est facultatif si votre moteur ne le prend pas en charge.
Adam Katz
2
Une option qui n'a pas encore été abordée est:
Inversez la corde.
Effectuez la correspondance sur la chaîne inversée.
Re-inversez les chaînes correspondantes.
Cela a l'avantage supplémentaire de pouvoir faire correspondre correctement les balises ouvertes échappées.
Disons que vous avez eu la chaîne suivante; String \"this "should" NOT match\" and "this \"should\" match"
Ici, \"this "should" NOT match\"ne devrait pas être apparié et "should"devrait l'être. En plus de cela, il this \"should\" matchdevrait être égalé et \"should\"non.
D'abord un exemple.
// 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"']
Bon, maintenant pour expliquer le RegExp. C'est l'expression rationnelle qui peut être facilement divisée en trois morceaux. 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 du Regulex de Jex
Il faut se rappeler que les expressions régulières ne sont pas une solution miracle pour tout ce qui est string-y. Certaines choses sont plus simples à faire avec un curseur et une recherche linéaire, manuelle. Un CFL ferait l'affaire assez trivialement, mais il n'y a pas beaucoup d'implémentations CFL (afaik).
Je me suis trompé sur regexpal et j'ai fini avec cette expression régulière: (Ne me demandez pas comment cela fonctionne, je comprends à peine même si je l'ai écrit lol)
J'ai rencontré un problème similaire en essayant de supprimer les chaînes entre guillemets qui peuvent interférer avec l'analyse de certains fichiers.
Je me suis retrouvé avec une solution en deux étapes qui surpasse toute expression régulière alambiquée que vous pouvez trouver:
line = line.replace("\\\"","\'");// Replace escaped quotes with something easier to handle
line = line.replaceAll("\"([^\"]*)\"","\"x\"");// Simple is beautiful
Si votre IDE est IntelliJ Idea, vous pouvez oublier tous ces maux de tête et stocker votre expression régulière dans une variable String et lorsque vous la copiez-collez à l'intérieur du guillemet double, elle passera automatiquement à un format acceptable pour les expressions régulières.
exemple en Java:
String s ="\"en_usa\":[^\\,\\}]+";
maintenant vous pouvez utiliser cette variable dans votre expression régulière ou n'importe où.
Réponses:
Fonctionne dans The Regex Coach et PCRE Workbench.
Exemple de test en JavaScript:
la source
(?:...)
est un groupe passif ou non capturant. Cela signifie qu'il ne peut pas être référencé ultérieurement./(["'])(?:[^\1\\]|\\.)*?\1/
var s = ' my \\"new\\" string and \"this should be matched\"';
, cette approche conduira à des résultats inattendus.Celui-ci provient de nanorc.sample disponible dans de nombreuses distributions Linux. Il est utilisé pour la coloration syntaxique des chaînes de style C
la source
var s = ' my \\"new\\" string and \"this should be matched\"';
, cette approche conduira à des résultats inattendus." \"(\\\\.|[^\\\"])*\" "
Comme fourni par ePharaoh, la réponse est
Pour appliquer ce qui précède aux chaînes entre guillemets simples ou doubles, utilisez
la source
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 volumineuses car certains compilateurs de modèles implémentent cela en utilisant la récursivité.
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 en évitant la plupart des débordements de pile.la source
Alterner les
\"
et les.
passes sur les guillemets échappés tandis que le quantificateur paresseux*?
garantit que vous ne dépassez pas la fin de la chaîne entre guillemets. Fonctionne avec les classes .NET Framework REla source
"\\"
var s = ' my \\"new\\" string and \"this should be matched\"';
/"(?:(?:\\"|[^"])*)"/g
cela devrait corrigerTiré directement d'
man perlre
un système Linux avec Perl 5.22.0 installé. En guise d'optimisation, cette expression régulière utilise la forme «posessive» des deux+
et*
pour empêcher le retour en arrière, car il est connu à l'avance qu'une chaîne sans guillemets fermants ne correspondrait dans aucun cas.la source
devrait fonctionner avec n'importe quelle chaîne entre guillemets
la source
Celui-ci fonctionne parfaitement sur PCRE et ne tombe pas avec StackOverflow.
Explication:
"
;.*?
{Lazy match}; se terminant par un caractère non d'échappement[^\\]
;(.*?[^\\])??
"
), mais elle peut être précédée d'un nombre pair de paires de signes d'échappement(\\\\)+
; et c'est Greedy (!) optionnel:((\\\\)+)?+
{Greedy matching}, la chaîne bacause peut être vide ou sans paires de fin!la source
"(.*?[^\\])?(\\\\)*"
en voici un qui fonctionne à la fois avec "et" et vous en ajoutez facilement d'autres au début.
il utilise la référence arrière (\ 1) qui correspond exactement à ce qui est dans le premier groupe ("ou ').
http://www.regular-expressions.info/backref.html
la source
[^\1]
devrait être remplacée par.
car il n'y a pas d'anti-back-reference, et cela n'a pas d'importance de toute façon. la première condition correspondra toujours avant que quelque chose de mauvais puisse arriver.[^\1]
avec.
aurait pour effet de changer cette expression rationnelle("|').*?\1
et il correspondrait"foo\"
à"foo \" bar"
. Cela dit, il[^\1]
est difficile de se mettre au travail. @ Mathiashansen - Vous êtes mieux avec le peu maniable et cher(?!\1).
(donc l'ensemble de la regex, avec un certain nettoyage d'efficacité, le serait(["'])(?:\\.|(?!\1).)*+\1
. Le+
est facultatif si votre moteur ne le prend pas en charge.Une option qui n'a pas encore été abordée est:
Cela a l'avantage supplémentaire de pouvoir faire correspondre correctement les balises ouvertes échappées.
Disons que vous avez eu la chaîne suivante;
String \"this "should" NOT match\" and "this \"should\" match"
Ici,\"this "should" NOT match\"
ne devrait pas être apparié et"should"
devrait l'être. En plus de cela, ilthis \"should\" match
devrait être égalé et\"should\"
non.D'abord un exemple.
Bon, maintenant pour expliquer le RegExp. C'est l'expression rationnelle qui peut être facilement divisée en trois morceaux. Comme suit:
C'est probablement beaucoup plus clair sous forme d'image: généré à l'aide du Regulex de Jex
Image sur github (Visualiseur d'expressions régulières JavaScript.) Désolé, je n'ai pas une réputation assez élevée pour inclure des images, donc, ce n'est qu'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
la source
Il faut se rappeler que les expressions régulières ne sont pas une solution miracle pour tout ce qui est string-y. Certaines choses sont plus simples à faire avec un curseur et une recherche linéaire, manuelle. Un CFL ferait l'affaire assez trivialement, mais il n'y a pas beaucoup d'implémentations CFL (afaik).
la source
Une version plus complète de https://stackoverflow.com/a/10786066/1794894
Cette version contient également
“
et fermer”
)la source
Je me suis trompé sur regexpal et j'ai fini avec cette expression régulière: (Ne me demandez pas comment cela fonctionne, je comprends à peine même si je l'ai écrit lol)
la source
Si elle est recherchée depuis le début, peut-être que cela peut fonctionner?
la source
J'ai rencontré un problème similaire en essayant de supprimer les chaînes entre guillemets qui peuvent interférer avec l'analyse de certains fichiers.
Je me suis retrouvé avec une solution en deux étapes qui surpasse toute expression régulière alambiquée que vous pouvez trouver:
Plus facile à lire et probablement plus efficace.
la source
Si votre IDE est IntelliJ Idea, vous pouvez oublier tous ces maux de tête et stocker votre expression régulière dans une variable String et lorsque vous la copiez-collez à l'intérieur du guillemet double, elle passera automatiquement à un format acceptable pour les expressions régulières.
exemple en Java:
maintenant vous pouvez utiliser cette variable dans votre expression régulière ou n'importe où.
la source