Comment obtenir la sous-chaîne à l' " It's big \"problem "
aide d'une expression régulière?
s = ' function(){ return " It\'s big \"problem "; }';
Comment obtenir la sous-chaîne à l' " It's big \"problem "
aide d'une expression régulière?
s = ' function(){ return " It\'s big \"problem "; }';
Réponses:
/"(?:[^"\\]|\\.)*"/
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);
(?:...)
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
\"(\\.|[^\"])*\"
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 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.
"(?:\\"|.)*?"
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
"\\"
/"(?:(?:\\"|[^"])*)"/g
cela devrait corriger
/"(?:[^"\\]++|\\.)*+"/
Tiré 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.
/(["\']).*?(?<!\\)(\\\\)*\1/is
devrait fonctionner avec n'importe quelle chaîne entre guillemets
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!"(.*?[^\\])?(\\\\)*"
en voici un qui fonctionne à la fois avec "et" et vous en ajoutez facilement d'autres au début.
("| ') (?: \\\ 1 | [^ \ 1]) *? \ 1
il utilise la référence arrière (\ 1) qui correspond exactement à ce qui est dans le premier groupe ("ou ').
[^\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, il this \"should\" match
devrait ê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 = 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"']
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
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
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).
Une version plus complète de https://stackoverflow.com/a/10786066/1794894
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
Cette version contient également
“
et fermer ”
)Si elle est recherchée depuis le début, peut-être que cela peut fonctionner?
\"((\\\")|[^\\])*\"
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
Plus facile à lire et probablement plus efficace.
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ù.