Regex para obtener una cadena entre llaves

115

Desafortunadamente, a pesar de haber tratado de aprender expresiones regulares al menos una vez al año durante tantos años como puedo recordar, siempre lo olvido, ya que las uso con poca frecuencia. Este año, mi resolución de año nuevo es no intentar aprender a regex nuevamente, así que este año, para salvarme de las lágrimas, se lo daré a Stack Overflow . (Remix de la última Navidad).

Quiero pasar una cadena en este formato {getThis}y que se me devuelva la cadena getThis. ¿Alguien podría ayudarme a cumplir con mi resolución de año nuevo?


Preguntas relacionadas sobre Stack Overflow:

ChrisInCambo
fuente
5
Esta pregunta se ha agregado a las Preguntas frecuentes sobre expresiones regulares de desbordamiento de pila , en "Advanced Regex-Fu".
aliteralmind
@Kobi: El FAQ es una wiki. Cualquiera puede editarlo. Así que edítalo.
aliteralmind

Respuestas:

44

Si su cadena siempre tendrá ese formato, una expresión regular es excesiva:

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

substring(1significa comenzar un carácter en (justo después del primero {) y ,g.length-1)significa tomar caracteres hasta (pero sin incluir) el carácter en la longitud de la cadena menos uno. Esto funciona porque la posición está basada en cero, g.length-1es decir, es la última posición.

Para lectores que no sean el póster original: si tiene que ser una expresión regular, utilícela /{([^}]*)}/si desea permitir cadenas vacías o /{([^}]+)}/si solo desea hacer coincidir cuando haya al menos un carácter entre las llaves. Descompostura:

  • /: inicia el patrón de expresiones regulares
    • {: una llave literalmente rizada
      • (: empezar a capturar
        • [: comienza a definir una clase de personajes para capturar
          • ^}: "cualquier cosa que no sea }"
        • ]: OK, esa es nuestra definición de clase completa
        • *: cualquier número de caracteres que coincida con esa clase que acabamos de definir
      • ): terminado de capturar
    • }: una llave literal debe seguir inmediatamente a lo que capturamos
  • /: finalizar el patrón de expresiones regulares
Kev
fuente
7
La subcadena es una de esas cosas que cambia según el idioma en el que trabaja. Javascript toma el índice para detenerse, PHP toma la longitud del resultado final deseado (a menos que sea negativo, en cuyo caso se necesita la cantidad de caracteres para eliminar) , C # es diferente de nuevo ... agradable y confuso.
jvenema
2
... y Python solo tiene corte, que en mi opinión es mejor que cualquier otra cosa: p.
Grant Paul
27
Dulce, pero no estoy seguro de cómo es una expresión regular. Quizás estaba pidiendo expresiones regulares, y vine aquí para la misma respuesta ... lamentablemente la respuesta no tiene nada que ver con la pregunta ...
baash05
5
@ baash05, si leíste toda la pregunta, el OP ni siquiera quería aprender expresiones regulares, así que no creo que sea el ejercicio académico que pareces estar sugiriendo.
Kev
2
Quería hacer -1 porque la pregunta está pidiendo expresiones regulares , estaba buscando expresiones regulares , pero la respuesta aceptada fue completamente inútil para mí (mientras que la pregunta parecía muy prometedora en sí misma). Después de leer el primer comentario, debo admitir que si hubiera respondido a esta pregunta primero, podría haber respondido de la misma manera / similar ... Así que al final, +1.
shadyyx
250

Tratar

/{(.*?)}/

Eso significa que debe coincidir con cualquier carácter entre {y}, pero no sea codicioso: busque la cadena más corta que termine en} (el? Deja de ser codicioso). Los paréntesis le permiten extraer la parte correspondiente.

Otra forma seria

/{([^}]*)}/

Esto coincide con cualquier carácter excepto un} char (otra forma de no ser codicioso)

Paul Dixon
fuente
esto es excelente, pero ¿es posible hacer coincidir algo entre un número variable de combinaciones de corchetes? Por ejemplo: "{esto debería coincidir} esto no debería {esto un poco debería de nuevo} y así {on}"? Me gustaría recuperar el valor, que no está entre corchetes. Además: no se usarán corchetes en la oración y no hay apilamiento (esto nunca ocurriría: "{algunos {texto}}"). ¿Alguien tiene una idea de cómo hacerlo :)? ¡Gracias! (PD: votó a favor de esta solución)
Igor
4
No captura todo entre las llaves, captura todo entre las llaves Y las llaves en sí. ¿Cómo harías para capturar SOLO lo que hay dentro de las llaves?
Reality-Torrent
1
Me gusta que no necesite escapar de las llaves aquí, ya que el analizador de expresiones regulares parece darse cuenta de que no son un cuantificador ... bueno, estoy haciendo esto en Python, pero supongo que las expresiones regulares de JavaScript funcionan así también
drevicko
3
Agregar un gal final lo convierte en una búsqueda global. Vea un ejemplo
práctico
1
@ Reality-Torrent, yo también vi que capturaba las llaves si especifico la opción g para obtener todas las coincidencias. Resulta que debería usar Regex.exec en un bucle en lugar de string.match en Javascript para tener la bandera g y permitir el grupo de captura. Ver 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
maullar
fuente
@meouw sa = s.split ("/ \ {([^}] +) \} /"); da un error de compilación. repetición ilegal, carácter de escape no válido.
likejudo
@Anil, parece que estás usando una cadena como argumento dividido en lugar de una expresión regular. ¿Que estás tratando de hacer?
maullido el
30

Prueba esto:

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

Por ejemplo

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

volverá gskinner.com, ssd.sd.

Mohamed Abo Elmagd
fuente
1
Genial, ¿puedes explicar por qué lo usas \}en el primer bloque?
Uzair Ali
1
Bonito, pero coincidirá con cualquier grupo que termine con }, incluso si no comienza con {.
Ahmad Ibrahim
1
Esta es la única respuesta correcta que realmente funciona.
pldg
Explicación: Si bien [^ \ {\}] + coincidirá con cualquier cosa que no sea una llave, la aserción de anticipación (? =}) Se asegurará de pasar solo las secciones que preceden a una llave. Con / ... / g obtenemos todas las apariciones, no solo la primera.
0 -_- 0
19

Aquí hay una solución simple usando javascript replace

var st = '{getThis}';

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

Como señala la respuesta aceptada anterior, el problema original se resuelve fácilmente con la subcadena, pero el uso de reemplazar puede resolver los casos de uso más complicados

Si tiene una cadena como "randomstring999 [fieldname]", utiliza un patrón ligeramente diferente para obtener fieldname

var nameAttr = "randomstring999[fieldname]";

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

Este funciona en Textmate y coincide con todo en un archivo CSS entre las llaves.

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

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

Si desea poder devolver más el contenido, envuélvalo todo en un paréntesis más de la siguiente manera:

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

y puede acceder a los contenidos a través de $ 1.

Esto también funciona para funciones, pero no lo he probado con llaves anidadas.

Alex Kessaris
fuente
14

Desea utilizar la búsqueda anticipada y la retrospectiva de expresiones regulares. Esto le dará solo lo que está dentro de las llaves:

(?<=\{)(.*?)(?=\})
Robert Cesaric
fuente
Debería haber una barra invertida que se escape de las llaves de arriba. Fueron despojados de mi sumisión.
Robert Cesaric
1
Gracias, esto me ayudó hoy.
ProfessionalAmateur
alguna desventaja de este método?
Somatik
5
@ Somatik: sí, ECMAScript no admite el avance y retroceso negativos.
RobG
Nota: este ejemplo funciona en Java. Devuelve todos los valores en todas las llaves.
Multiplexor
13

Prueba esto

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"]
Hemadri Dasari
fuente
1
Exactamente lo que quería :) esto devolverá el resultado sin llaves, las otras soluciones regresan con él
Al-Mothafar
Excelente, la mejor respuesta aquí.
michal.jakubeczy
4

Regex para obtener matrices de cadenas con llaves encerradas ocurre en cadena, en lugar de simplemente encontrar la primera aparición.

 /\{([^}]+)\}/gm 
Er. Mohit Agrawal
fuente
4

He examinado las otras respuestas y parece que les falta una lógica vital. es decir, seleccione todo entre dos corchetes CONSECUTIVOS, pero NO los corchetes

así que aquí está mi respuesta

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

.replace(/.*{(.*)}.*/, '$1')Desafortunadamente, el más simple devuelve la cadena completa si la expresión regular no coincide. El fragmento de código anterior puede detectar más fácilmente una coincidencia.

Curtis Yallop
fuente
3

Pruebe este, de acuerdo con http://www.regextester.com , normalmente funciona para js .

([^{]*?)(?=\})

Павло Коменда
fuente
3
para selección múltiple puede utilizar /([^{]*?)\w(?=\})/gmi
Павло Коменда
2

Puede usar esta recursividad de expresiones regulares para hacer coincidir todo, incluso otro {}(como un texto JSON):

\{([^()]|())*\}
p3quod
fuente
Bien, pero esto solo captura el contenido dentro de llaves anidadas
Dominic
no captura si el contenido contiene ()
Mert Mertce
1

Incluso esto me ayuda mientras trato de resolver el problema de alguien,

Dividir el contenido dentro de llaves ( {}) que tiene un patrón como, {'day': 1, 'count': 100}.

Por ejemplo:

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

Salida:

[{'day': 1, 'count': 100}] [{'day': 2, 'count': 100}]
Shudipta Sharma
fuente