¿Cómo extraigo el texto que se encuentra entre paréntesis (corchetes)?

224

Tengo una cadena User name (sales)y quiero extraer el texto entre paréntesis, ¿cómo haría esto?

Sospecho de una subcadena, pero no puedo entender cómo leer hasta el corchete de cierre, la longitud del texto variará.

gotqn
fuente
2
Muéstranos lo que has probado. ¿Has mirado usando expresiones regulares?
George Stocker

Respuestas:

445

Si desea mantenerse alejado de las expresiones regulares, la forma más simple que se me ocurre es:

string input = "User name (sales)";
string output = input.Split('(', ')')[1];
Gelatina ama
fuente
91
Honestamente, esto debería haber sido seleccionado como la respuesta.
Pat Lindley
1
¿No se contrae más en input.Split ("()". ToCharArray ()) [1]
prabhakaran
14
y en caso de que quiera usar la misma lógica para seleccionar múltiples:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE
1
tenga en cuenta que esta solución salestambién se extrae de cadenas de entrada que contienen )sales(, (sales(etc.
Stefano Spinucci
435

Una forma muy simple de hacerlo es mediante el uso de expresiones regulares:

Regex.Match("User name (sales)", @"\(([^)]*)\)").Groups[1].Value

Como respuesta al comentario (muy divertido), aquí está el mismo Regex con alguna explicación:

\(             # Escaped parenthesis, means "starts with a '(' character"
    (          # Parentheses in a regex mean "put (capture) the stuff 
               #     in between into the Groups array" 
       [^)]    # Any character that is not a ')' character
       *       # Zero or more occurrences of the aforementioned "non ')' char"
    )          # Close the capturing group
\)             # "Ends with a ')' character"
Diadistis
fuente
504
Me encanta cuando la gente dice "una manera simple es usar expresiones regulares" y luego ofrecer lo que equivale a una cadena de jeroglíficos indescifrables (es especialmente divertido cuando diferentes personas sugieren expresiones regulares y cada una presenta un conjunto diferente de jeroglíficos para el mismo problema) ) :)
Deltics
47
No hay suficientes respuestas en la pila que realmente expliquen lo que está sucediendo. Gracias por la maravillosa explicación.
Sandy Gifford
Si está usando '@' al principio, creo que no necesita escapar del paréntesis.
rango1
10
@ rank1 debes escapar del paréntesis. Lo que @ ofrece aquí es que no necesita escapar de las barras diagonales inversas. Entonces, sin la @ sería como "\\ (([^)] *) \\)".
Diadistis
Sin embargo, esto no maneja bien los grupos anidados. Cambiado avar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen
91

Suponiendo que solo tiene un par de paréntesis.

string s = "User name (sales)";
int start = s.IndexOf("(") + 1;
int end = s.IndexOf(")", start);
string result = s.Substring(start, end - start);
Ross Goddard
fuente
77
Inicio + 1 en la subcadena es más correcto si desea "ventas" en lugar de (ventas)
Joze
1
¿Qué pasará s = "Nombre de usuario (Ventas)"?
dotnetstep
@dotnetstep tienes razón debería ser int end = s.IndexOf(")", start);. He puesto en cola una edición ...
ChrisD
1
"(" .Length; es mejor que +1. Envió una edición. También agregó una función.
Ave
24

Utiliza esta función:

public string GetSubstringByString(string a, string b, string c)
    {
        return c.Substring((c.IndexOf(a) + a.Length), (c.IndexOf(b) - c.IndexOf(a) - a.Length));
    }

y aquí está el uso:

GetSubstringByString("(", ")", "User name (sales)")

y la salida sería:

sales
artfulhacker
fuente
16

Las expresiones regulares pueden ser la mejor herramienta aquí. Si no está familiarizado con ellos, le recomiendo que instale Expresso , una pequeña herramienta genial para expresiones regulares.

Algo como:

Regex regex = new Regex("\\((?<TextInsideBrackets>\\w+)\\)");
string incomingValue = "Username (sales)";
string insideBrackets = null;
Match match = regex.Match(incomingValue);
if(match.Success)
{
    insideBrackets = match.Groups["TextInsideBrackets"].Value;
}
Jennifer
fuente
14
string input = "User name (sales)";

string output = input.Substring(input.IndexOf('(') + 1, input.IndexOf(')') - input.IndexOf('(') - 1);
Nick Allen
fuente
1
Por supuesto, solo debe calcular la ubicación del primer paréntesis una vez.
Martin Brown
En el caso de que tenga paréntesis internos, por ejemplo, input = "User name (sales(1))es posible que desee utilizar el input.LastIndexOf(')')que funcionará si hay paréntesis internos o no.
Ben
13

¿Una expresión regular tal vez? Creo que esto funcionaría ...

\(([a-z]+?)\)
escalofríos42
fuente
7
using System;
using System.Text.RegularExpressions;

private IEnumerable<string> GetSubStrings(string input, string start, string end)
{
    Regex r = new Regex(Regex.Escape(start) +`"(.*?)"`  + Regex.Escape(end));
    MatchCollection matches = r.Matches(input);
    foreach (Match match in matches)
    yield return match.Groups[1].Value;
}
Bilal Mrad
fuente
4

Use una expresión regular:

string test = "(test)"; 
string word = Regex.Match(test, @"\((\w+)\)").Groups[1].Value;
Console.WriteLine(word);
Will Dean
fuente
4
int start = input.IndexOf("(") + 1;
int length = input.IndexOf(")") - start;
output = input.Substring(start, length);
Gustavo Baiocchi Costa
fuente
2
input.Remove(input.IndexOf(')')).Substring(input.IndexOf('(') + 1);
Rockcoder
fuente
2

El regexmétodo es superior, creo, pero si querías usar el humildesubstring

string input= "my name is (Jayne C)";
int start = input.IndexOf("(");
int stop = input.IndexOf(")");
string output = input.Substring(start+1, stop - start - 1);

o

string input = "my name is (Jayne C)";
string output  = input.Substring(input.IndexOf("(") +1, input.IndexOf(")")- input.IndexOf("(")- 1);
A pesar de
fuente
1

Aquí hay una función legible de uso general que evita el uso de expresiones regulares:

// Returns the text between 'start' and 'end'.
string ExtractBetween(string text, string start, string end)
{
  int iStart = text.IndexOf(start);
  iStart = (iStart == -1) ? 0 : iStart + start.Length;
  int iEnd = text.LastIndexOf(end);
  if(iEnd == -1)
  {
    iEnd = text.Length;
  }
  int len = iEnd - iStart;

  return text.Substring(iStart, len);
}

Para llamarlo en su ejemplo particular, puede hacer:

string result = ExtractBetween("User name (sales)", "(", ")");
ChaimG
fuente
1

Me parece que las expresiones regulares son extremadamente útiles pero muy difíciles de escribir. Entonces, investigué un poco y encontré esta herramienta que hace que escribirlos sea tan fácil.

No se aleje de ellos porque la sintaxis es difícil de entender. Pueden ser muy poderosos.

katyholb
fuente
2
Bienvenido a SO! Este es un buen consejo, pero no debería haberse publicado como respuesta. Los consejos generales como este deberían publicarse como comentarios, si es que lo hacen. Una respuesta debe abordar el problema específico del autor de la pregunta. Sé que todavía no tienes suficientes puntos de reputación para publicar comentarios, pero esto es exactamente por qué existe el umbral de representación. Cuando haya estado un poco más de tiempo verá que la gente siempre recomienda herramientas como Rubular (en los comentarios, por supuesto). En otras palabras, este consejo puede ser útil, pero no es urgente.
Alan Moore
0

Encontré esto mientras buscaba una solución para una implementación muy similar.

Aquí hay un fragmento de mi código real. Inicia la subcadena desde el primer carácter (índice 0).

 string separator = "\n";     //line terminator

 string output;
 string input= "HowAreYou?\nLets go there!";

 output = input.Substring(0, input.IndexOf(separator)); 
nikk
fuente
Esto no responde lo que ha pedido el OP.
dicemaster
0

Este código es más rápido que la mayoría de las soluciones aquí (si no todas), empaquetado como método de extensión de cadena , no admite el anidamiento recursivo:

public static string GetNestedString(this string str, char start, char end)
{
    int s = -1;
    int i = -1;
    while (++i < str.Length)
        if (str[i] == start)
        {
            s = i;
            break;
        }
    int e = -1;
    while(++i < str.Length)
        if (str[i] == end)
        {
            e = i;
            break;
        }
    if (e > s)
        return str.Substring(s + 1, e - s - 1);
    return null;
}

Este es un poco más largo y más lento, pero maneja el anidamiento recursivo más bien:

public static string GetNestedString(this string str, char start, char end)
{
    int s = -1;
    int i = -1;
    while (++i < str.Length)
        if (str[i] == start)
        {
            s = i;
            break;
        }
    int e = -1;
    int depth = 0;
    while (++i < str.Length)
        if (str[i] == end)
        {
            e = i;
            if (depth == 0)
                break;
            else
                --depth;
        }
        else if (str[i] == start)
            ++depth;
    if (e > s)
        return str.Substring(s + 1, e - s - 1);
    return null;
}
watbywbarif
fuente