Regex para obter string entre chaves


115

Infelizmente, apesar de ter tentado aprender regex pelo menos uma vez por ano durante tantos anos quanto consigo me lembrar, sempre me esqueço de usá-los com pouca frequência. Este ano, minha resolução de ano novo é não tentar aprender regex novamente - então, este ano, para me salvar das lágrimas, vou entregá-lo ao Stack Overflow . (Último remix de Natal).

Quero passar uma string neste formato {getThis}e retornar a string getThis. Alguém poderia me ajudar a cumprir minha resolução de ano novo?


Perguntas relacionadas no Stack Overflow:


5
Esta pergunta foi adicionada às Perguntas frequentes sobre expressões regulares do Stack Overflow , em "Advanced Regex-Fu".
aliteralmind de

@Kobi: O FAQ é um wiki. Qualquer um pode editá-lo. Então edite.
aliteralmind

Respostas:


44

Se sua string será sempre nesse formato, uma regex é um exagero:

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

substring(1significa iniciar um caractere (logo após o primeiro {) e ,g.length-1)significa levar caracteres até (mas não incluindo) o caractere no comprimento da string menos um. Isso funciona porque a posição é baseada em zero, ou seja, g.length-1é a última posição.

Para leitores que não sejam o autor da postagem original: Se tiver que ser uma regex, use /{([^}]*)}/se quiser permitir strings vazias ou /{([^}]+)}/se quiser corresponder apenas quando houver pelo menos um caractere entre as chaves. Demolir:

  • /: inicia o padrão regex
    • {: uma chave literal
      • (: começar a capturar
        • [: comece a definir uma classe de personagens para capturar
          • ^}: "qualquer coisa diferente de }"
        • ]: OK, essa é toda a nossa definição de classe
        • *: qualquer número de caracteres correspondentes à classe que acabamos de definir
      • ): captura concluída
    • }: uma chave literal deve seguir imediatamente o que capturamos
  • /: termina o padrão regex

7
Substring é uma daquelas coisas que muda com base na linguagem em que você trabalha. Javascript leva o índice para parar, PHP leva o comprimento do resultado final desejado (a menos que seja negativo, caso em que leva o número de caracteres para remover) , C # é diferente de novo ... agradável e confuso.
jvenema

2
... e Python apenas tem fatiamento, que IMO é melhor do que qualquer outra coisa: p.
Grant Paul,

27
Legal, mas não tenho certeza de como essa é uma expressão regular. Talvez ele estivesse pedindo regex e eu vim aqui pela mesma resposta .. infelizmente, a resposta não tem nada a ver com a pergunta ..
baash05

5
@ baash05, se você leu a pergunta inteira, o OP nem mesmo queria aprender regex, então não acho que seja o exercício acadêmico que você parece estar sugerindo.
Kev

2
Eu queria fazer -1 porque a pergunta é pedir regex , eu estava procurando por regex , mas a resposta aceita foi completamente inútil para mim (embora a pergunta pareça muito promissora). Depois de ler o primeiro comentário, devo admitir que se eu fosse responder a essa pergunta primeiro, poderia ter respondido da mesma forma / semelhante ... Então, no final, +1.
shadyyx

250

Experimentar

/{(.*?)}/

Isso significa que combine qualquer caractere entre {e}, mas não seja ganancioso - combine a string mais curta que termina com} (o? Para * de ser ganancioso). Os parênteses permitem que você extraia a parte correspondente.

Outra forma seria

/{([^}]*)}/

Corresponde a qualquer caractere, exceto a} char (outra maneira de não ser ganancioso)


isso é excelente, mas é possível combinar qualquer coisa entre um número variável de combinações de chaves? Por exemplo: "{isto deve ser correspondido} isto não deveria {isto meio que deveria novamente} e assim {por diante}"? Eu gostaria de recuperar o valor, que não está entre chaves. Além disso: colchetes não serão usados ​​na frase e não há empilhamento (isso nunca ocorreria: "{algum {texto}}"). Alguém tem uma ideia de como fazer isso :)? Obrigado! (ps: voto positivo nesta solução)
Igor

4
Ele não captura tudo entre as chaves, ele captura tudo entre as chaves E as próprias chaves. Como você faria para capturar APENAS o que está dentro das chaves?
Reality-Torrent

1
Eu gosto que você não precise escapar das chaves aqui, pois o analisador regex parece perceber que eles não são um quantificador ... bem, estou fazendo isso em python, mas presumo que regexes javascript funcionem assim também
drevicko

3
Adicionar um gno final torna a pesquisa global. Veja um exemplo
prático

1
@ Reality-Torrent, também vi que ele capturou as chaves se eu especificar a opção g para obter todas as correspondências. Acontece que eu deveria usar Regex.exec em um loop em vez de string.match em Javascript para ter o sinalizador g e permitir o grupo de captura. Consulte developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
frank

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 ("/ \ {([^}] +) \} /"); dá um erro de compilação. repetição ilegal, caractere de escape inválido.
judô

@Anil, você parece estar usando uma string como argumento de divisão em vez de uma expressão regular. O que você está tentando fazer?
meouw

30

Experimente isto:

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

Por exemplo

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

vai voltar gskinner.com, ssd.sd.


1
Ótimo, você pode explicar por que você usa \}no primeiro bloco?
Uzair Ali

1
Boa, mas vai corresponder a qualquer grupo que termine com }, mesmo que não comece com {.
Ahmad Ibrahim

1
Esta é a única resposta correta que realmente funciona.
pldg

Explicação: Embora [^ \ {\}] + corresponda a qualquer coisa que não seja uma chave, a afirmação antecipada (? =}) Garantirá que apenas as seções anteriores a uma chave serão transmitidas. Com / ... / g obtemos todas as ocorrências, não apenas a primeira.
0 -_- 0

19

Aqui está uma solução simples usando substituição de javascript

var st = '{getThis}';

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

Como a resposta aceita acima aponta, o problema original é facilmente resolvido com substring, mas usar substituir pode resolver os casos de uso mais complicados

Se você tem uma string como "randomstring999 [fieldname]", você usa um padrão ligeiramente diferente para obter fieldname

var nameAttr = "randomstring999[fieldname]";

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

15

Este funciona no Textmate e corresponde a tudo em um arquivo CSS entre as chaves.

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

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

Se você quiser mais poder retornar o conteúdo, envolva-o em mais um conjunto de parênteses da seguinte forma:

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

e você pode acessar o conteúdo por meio de $ 1.

Isso também funciona para funções, mas não testei com chaves aninhadas.


14

Você deseja usar regex lookahead e lookbehind. Isso fornecerá apenas o que está dentro das chaves:

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

Deve haver uma barra invertida escapando das chaves acima. Eles foram eliminados na minha apresentação.
Robert Cesaric

1
Obrigado, isso me ajudou hoje.
ProfessionalAmateur

alguma desvantagem deste método?
Somatik

5
@ Somatik — sim, lookahead negativo e posterior não são suportados no ECMAScript.
RobG

Nota: este exemplo funciona em Java. Retorna todos os valores em todas as chaves.
Multiplexor

13

Tente isto

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
Exatamente o que eu queria :) isso vai retornar o resultado sem chaves, as outras soluções voltam com ele
Al-Mothafar 17/10/18

Excelente, a melhor resposta aqui.
michal.jakubeczy

4

Regex para obter matrizes de string com chaves entre chaves ocorre na string, em vez de apenas encontrar a primeira ocorrência.

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

4

Procurei outras respostas e parece que falta uma lógica vital nelas. ou seja, selecione tudo entre dois colchetes CONSECUTIVOS, mas NÃO os colchetes

então, aqui está minha resposta

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

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

O mais simples, .replace(/.*{(.*)}.*/, '$1')infelizmente, retorna a string inteira se a regex não corresponder. O trecho de código acima pode detectar uma correspondência mais facilmente.



2

Você pode usar essa recursão regex para corresponder a tudo, até mesmo outro {}(como um texto JSON):

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

Legal, mas isso apenas captura o conteúdo entre colchetes
Dominic

não captura se o conteúdo contém ()
Mert Mertce

1

Até mesmo isso me ajuda a tentar resolver o problema de alguém,

Divida o conteúdo entre colchetes ( {}) com um padrão como {'day': 1, 'count': 100},.

Por exemplo:

#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; 
}

Resultado:

[{'day': 1, 'count': 100}] [{'day': 2, 'count': 100}]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.