Regex pour obtenir une chaîne entre accolades


115

Malheureusement, malgré avoir essayé d'apprendre les regex au moins une fois par an pendant autant d'années que je me souvienne, j'oublie toujours car je les utilise si rarement. Cette année, ma résolution du nouvel an est de ne pas essayer d'apprendre à nouveau l'expression régulière - Donc cette année, pour me sauver des larmes, je la donnerai à Stack Overflow . (Dernier remix de Noël).

Je veux passer une chaîne dans ce format {getThis}et recevoir la chaîne getThis. Quelqu'un pourrait-il m'aider à m'en tenir à ma résolution du nouvel an?


Questions connexes sur Stack Overflow:


5
Cette question a été ajoutée à la FAQ sur les expressions régulières Stack Overflow , sous "Advanced Regex-Fu".
aliteralmind

@Kobi: La FAQ est un wiki. Tout le monde peut le modifier. Alors modifiez-le.
aliteralmind

Réponses:


44

Si votre chaîne sera toujours de ce format, une expression régulière est excessive:

>>> var g='{getThis}';
>>> g.substring(1,g.length-1)
"getThis"

substring(1signifie commencer un caractère dans (juste après le premier {) et ,g.length-1)signifie prendre des caractères jusqu'à (mais non compris) le caractère à la longueur de la chaîne moins un. Cela fonctionne car la position est basée sur zéro, c'est-à-dire g.length-1la dernière position.

Pour les lecteurs autres que l'affiche originale: s'il doit s'agir d'une expression régulière, utilisez cette option /{([^}]*)}/si vous souhaitez autoriser les chaînes vides, ou /{([^}]+)}/si vous souhaitez effectuer une correspondance uniquement lorsqu'il y a au moins un caractère entre les accolades. Panne:

  • /: démarrer le modèle regex
    • {: une accolade littérale
      • (: commencer à capturer
        • [: commencez à définir une classe de caractères à capturer
          • ^}: "autre chose que }"
        • ]: OK, c'est toute notre définition de classe
        • *: n'importe quel nombre de caractères correspondant à cette classe que nous venons de définir
      • ): capture terminée
    • }: une accolade littérale doit immédiatement suivre ce que nous avons capturé
  • /: terminer le modèle regex

7
La sous-chaîne est l'une de ces choses qui change en fonction de la langue dans laquelle vous travaillez. Javascript prend l'index pour s'arrêter, PHP prend la longueur du résultat final souhaité (sauf s'il est négatif, auquel cas il faut le nombre de caractères à supprimer) , C # est encore différent ... sympa et déroutant.
jvenema

2
... et Python vient de trancher, ce que l'OMI est meilleur que toute autre chose: p.
Grant Paul

27
Doux, mais je ne sais pas comment c'est une expression régulière. Peut-être qu'il demandait une expression régulière, et je suis venu ici pour la même réponse .. malheureusement, la réponse n'a rien à voir avec la question ..
baash05

5
@ baash05, si vous lisez toute la question, l'OP ne voulait même pas apprendre les regex, donc je ne pense pas que ce soit l'exercice académique que vous semblez suggérer.
Kev

2
Je voulais faire -1 parce que la question demandait des regex , je cherchais des regex , mais la réponse acceptée était complètement inutile pour moi (alors que la question me paraissait très prometteuse). Après avoir lu le premier commentaire, je dois admettre que si je devais d'abord répondre à cette question, j'aurais pu répondre de la même manière / d'une manière similaire ... Donc à la fin, +1.
shadyyx

250

Essayer

/{(.*?)}/

Cela signifie, correspond à n'importe quel caractère entre {et}, mais ne soyez pas gourmand - correspond à la chaîne la plus courte qui se termine par} (le? Arrête * d'être gourmand). Les parenthèses vous permettent d'extraire la partie correspondante.

Une autre façon serait

/{([^}]*)}/

Cela correspond à n'importe quel caractère sauf un} char (une autre façon de ne pas être gourmand)


c'est excellent, mais est-il possible de faire correspondre quelque chose entre un nombre variable de combinaisons de crochets bouclés? Par exemple: "{cela devrait correspondre} cela ne devrait pas {ce genre devrait encore} et ainsi {on}"? Je voudrais récupérer la valeur, qui n'est pas entre accolades. Aussi: les accolades ne seront pas utilisées dans la phrase et il n'y a pas d'empilement (cela ne se produirait jamais: "{some {text}}"). Quelqu'un a une idée de comment le faire :)? Merci! (ps: a voté pour cette solution)
Igor

4
Il ne capture pas tout entre les accolades, il capture tout entre les accolades ET les accolades eux-mêmes. Comment feriez-vous pour capturer UNIQUEMENT ce qui se trouve entre les accolades?
Reality-Torrent

1
J'aime le fait que vous n'ayez pas besoin d'échapper aux accolades ici car l'analyseur de regex semble se rendre compte qu'il ne s'agit pas d'un quantificateur ... eh bien, je fais cela en python, mais je suppose que les expressions rationnelles javascript fonctionnent comme ça aussi
drevicko

3
L'ajout d'un gà la fin en fait une recherche globale. Voir un exemple de travail
Benjamin

1
@ Reality-Torrent, j'ai aussi vu qu'il capturait les accolades si je spécifiais l'option g pour obtenir toutes les correspondances. Il s'avère que je devrais utiliser Regex.exec dans une boucle au lieu de string.match en Javascript pour avoir à la fois l'indicateur g et permettre le groupe de capture. Voir developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
franc

150
/\{([^}]+)\}/

/        - delimiter
\{       - opening literal brace escaped because it is a special character used for quantifiers eg {2,3}
(        - start capturing
[^}]     - character class consisting of
    ^    - not
    }    - a closing brace (no escaping necessary because special characters in a character class are different)
+        - one or more of the character class
)        - end capturing
\}       - the closing literal brace
/        - delimiter

@meouw sa = s.split ("/ \ {([^}] +) \} /"); donne une erreur de compilation. répétition illégale, caractère d'échappement invalide.
likejudo

@Anil, vous semblez utiliser une chaîne comme argument de fractionnement plutôt qu'une expression régulière. Qu'essayez-vous de faire?
meouw du

30

Essaye ça:

/[^{\}]+(?=})/g

Par exemple

Welcome to RegExr v2.1 by #{gskinner.com},  #{ssd.sd} hosted by Media Temple!

sera de retour gskinner.com, ssd.sd.


1
Super, pouvez-vous expliquer pourquoi vous utilisez \}dans le premier bloc?
Uzair Ali

1
Bien, mais qui correspondra à n'importe quel groupe qui se termine par }, même s'il ne commence pas par {.
Ahmad Ibrahim

1
C'est la seule bonne réponse qui fonctionne réellement.
pldg

Explication: Bien que [^ \ {\}] + corresponde à tout ce qui n'est pas une accolade, l'assertion d'anticipation (? =}) S'assurera de ne transmettre que les sections précédant une accolade. Avec / ... / g, nous obtenons toutes les occurrences, pas seulement la première.
0 -_- 0

19

Voici une solution simple utilisant javascript replace

var st = '{getThis}';

st = st.replace(/\{|\}/gi,''); // "getThis"

Comme le souligne la réponse acceptée ci-dessus, le problème d'origine est facilement résolu avec une sous-chaîne, mais l'utilisation de replace peut résoudre les cas d'utilisation les plus compliqués.

Si vous avez une chaîne comme "randomstring999 [fieldname]", vous utilisez un modèle légèrement différent pour obtenir fieldname

var nameAttr = "randomstring999[fieldname]";

var justName = nameAttr.replace(/.*\[|\]/gi,''); // "fieldname"

15

Celui-ci fonctionne dans Textmate et correspond à tout ce qui se trouve dans un fichier CSS entre les accolades.

\{(\s*?.*?)*?\}

selector {. . matches here including white space. . .}

Si vous souhaitez pouvoir renvoyer davantage le contenu, placez-le dans un autre jeu de parenthèses comme ceci:

\{((\s*?.*?)*?)\}

et vous pouvez accéder au contenu via $ 1.

Cela fonctionne également pour les fonctions, mais je ne l'ai pas testé avec des accolades imbriquées.


14

Vous voulez utiliser lookahead et lookbehind regex. Cela ne vous donnera que ce qui se trouve à l'intérieur des accolades:

(?<=\{)(.*?)(?=\})

Il devrait y avoir une barre oblique inverse échappant aux accolades ci-dessus. Ils ont été dépouillés dans ma soumission.
Robert Cesaric

1
Merci, cela m'a aidé aujourd'hui.
ProfessionalAmateur

des inconvénients de cette méthode?
Somatik

5
@ Somatik: oui, la recherche avant et arrière négative n'est pas prise en charge dans ECMAScript.
RobG

Remarque: cet exemple fonctionne en Java. Renvoie toutes les valeurs entre toutes les accolades.
Multiplexeur

13

Essaye ça

let path = "/{id}/{name}/{age}";
const paramsPattern = /[^{\}]+(?=})/g;
let extractParams = path.match(paramsPattern);
console.log("extractParams", extractParams) // prints all the names between {} = ["id", "name", "age"]

1
Le exactement ce que je voulais :) cela renverra le résultat sans accolades, les autres solutions reviennent avec lui
Al-Mothafar

Excellent, la meilleure réponse ici.
michal.jakubeczy

4

L'expression régulière pour obtenir des tableaux de chaînes avec des accolades entourées se produit dans une chaîne, plutôt que de simplement rechercher la première occurrence.

 /\{([^}]+)\}/gm 

4

J'ai examiné les autres réponses et une logique vitale semble leur manquer. c'est-à-dire, sélectionnez tout entre deux crochets CONSÉCUTIFS, mais PAS les crochets

alors, voici ma réponse

\{([^{}]+)\}

3
var re = /{(.*)}/;
var m = "{helloworld}".match(re);
if (m != null)
    console.log(m[0].replace(re, '$1'));

Le plus simple .replace(/.*{(.*)}.*/, '$1')renvoie malheureusement la chaîne entière si l'expression régulière ne correspond pas. L'extrait de code ci-dessus peut détecter plus facilement une correspondance.



2

Vous pouvez utiliser cette récursivité regex pour faire correspondre tout entre les deux, même un autre {}(comme un texte JSON):

\{([^()]|())*\}

Bien, mais cela ne capture que le contenu à l'intérieur d'accolades imbriquées
Dominic

ne capture pas si le contenu contient ()
Mert Mertce

1

Même cela m'aide en essayant de résoudre le problème de quelqu'un,

Diviser le contenu à l' intérieur des accolades ( {}) ayant un motif analogue, {'day': 1, 'count': 100}.

Par exemple:

#include <iostream> 
#include <regex> 
#include<string> 
using namespace std; 

int main() 
{ 
    //string to be searched
    string s = "{'day': 1, 'count': 100}, {'day': 2, 'count': 100}";

    // regex expression for pattern to be searched 
    regex e ("\\{[a-z':, 0-9]+\\}");
    regex_token_iterator<string::iterator> rend;

    regex_token_iterator<string::iterator> a ( s.begin(), s.end(), e );
    while (a!=rend) cout << " [" << *a++ << "]";
    cout << endl;

    return 0; 
}

Production:

[{'day': 1, 'count': 100}] [{'day': 2, 'count': 100}]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.