web-dev-qa-db-fra.com

Regex pour chaîne entre guillemets et guillemets

Comment obtenir la sous-chaîne " It's big \"problem " en utilisant une expression régulière?

s = ' function(){  return " It\'s big \"problem  ";  }';     
97
Andrii Kasian
/"(?:[^"\\]|\\.)*"/

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);

124
PhiLho

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

\"(\\.|[^\"])*\"
27
Darrell

Selon ePharaoh, la réponse est:

/"([^"\\]*(\\.[^"\\]*)*)"/

Pour que ce qui précède s'applique aux chaînes entre guillemets simples ou doubles, utilisez

/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
13
Guy Bedford

La plupart des solutions fournies ici utilisent des chemins de répétition alternatifs, à savoir (A | B) *.

Vous pouvez rencontrer des dépassements de pile sur des entrées volumineuses, car certains compilateurs de modèles l'implémentent à l'aide de la récursion.

Java, par exemple: http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=6337993

Quelque chose comme ceci: "(?:[^"\\]*(?:\\.)?)*", ou celle fournie par Guy Bedford réduira le nombre d’étapes d’analyse syntaxique en évitant la plupart des débordements de pile.

8
"(?:\\"|.)*?"

Alterner le \" et le . passe sur les guillemets échappés, tandis que le quantificateur paresseux *? vous assure de ne pas dépasser la fin de la chaîne citée. Fonctionne avec les classes .NET Framework RE

8
Tosh Afanasiev
/"(?:[^"\\]++|\\.)*+"/

Tiré directement de man perlre sur un système Linux sur lequel Perl 5.22.0 est installé . En optimisation, cette expression rationnelle utilise la forme 'possessive' de + et * pour empêcher les retours arrière, car on sait auparavant qu'une chaîne sans fermeture la citation ne correspondrait en aucun cas.

6
ack

Celui-ci fonctionne parfaitement sur PCRE et ne tombe pas avec StackOverflow.

"(.*?[^\\])??((\\\\)+)?+"

Explication:

  1. Chaque chaîne citée commence par Char: ";
  2. Il peut contenir n'importe quel nombre de caractères: .*? {Match fictif}; se terminant par un caractère non d'échappement [^\\];
  3. Statement (2) est Lazy (!) Facultatif car la chaîne peut être vide (""). Donc: (.*?[^\\])??
  4. Enfin, chaque chaîne citée se termine par Char ("), mais peut être précédée du nombre pair de paires de signes d'échappement (\\\\)+; et c'est Greedy (!) optionnel: ((\\\\)+)?+ {Matching glouton}, bacause string peut être vide ou sans fin paire.
4
Vadim Sayfi
/(["\']).*?(?<!\\)(\\\\)*\1/is

devrait fonctionner avec n'importe quelle chaîne citée

en voici un qui fonctionne 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 se trouve dans le premier groupe ("ou"). 

http://www.regular-expressions.info/backref.html

1
mathias hansen

Je me suis trompé à regexpal et je me suis retrouvé avec cette regex: (Ne me demandez pas comment ça marche, je comprends à peine même si je l’ai écrit lol)

"(([^"\\]?(\\\\)?)|(\\")+)+"
0
Petter Thowsen

J'ai rencontré un problème similaire en essayant de supprimer les chaînes entre guillemets susceptibles d'interférer avec l'analyse de certains fichiers.

Je me suis retrouvé avec une solution en deux étapes qui bat toutes les expressions rationnelles compliquées que vous pouvez proposer:

 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.

0

Si on cherche depuis le début, peut-être que ça peut marcher?

\"((\\\")|[^\\])*\"
0
user2267983

Une version plus complète de https://stackoverflow.com/a/10786066/1794894

/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/   

Cette version contient aussi

  1. Longueur minimum du devis de 50
  2. Type supplémentaire de guillemets (ouvrir et fermer )
0
Rvanlaak

Une option qui n'a pas encore été abordée est:

  1. Inverser la chaîne.
  2. Effectuez la correspondance sur la chaîne inversée.
  3. Réinverse les chaînes correspondantes.

Cela a l'avantage supplémentaire de pouvoir associer 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 devrait pas être apparié et "should" devrait être . En plus de cela this \"should\" match devrait être apparié 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 pour expliquer la RegExp . C’est l’expression rationnelle qui peut être facilement décomposé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é avec Regulex de Jex

Image sur github (Visualizer d'expressions régulières JavaScript.) Désolé, ma réputation n'est pas assez grande pour inclure des images, il ne s'agit donc que d'un lien.

Voici un résumé d'un exemple de fonction utilisant ce concept un peu plus avancé: https://Gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js

0
scagood

Il faut se rappeler que les expressions rationnelles ne sont pas une solution miracle pour tout ce qui est string-y. Certaines choses sont plus simples à faire avec un curseur et linéaire, manuel, à la recherche. Un CFL ferait l'affaire assez trivialement, mais il n'y a pas beaucoup d'implémentations de CFL (autant que je sache).

0
Henrik Paul