Como extrair texto entre parênteses (colchetes)?


224

Eu tenho uma string User name (sales)e quero extrair o texto entre colchetes, como eu faria isso?

Suspeito de sub-string, mas não sei como ler até o colchete, o tamanho do texto variará.


2
Mostre-nos o que você tentou. Você já olhou usando expressões regulares?
George Stocker

Respostas:


445

Se você deseja evitar expressões regulares, a maneira mais simples de pensar é:

string input = "User name (sales)";
string output = input.Split('(', ')')[1];

91
Honestamente, isso deveria ter sido selecionado como a resposta.
Pat Lindley

1
Não é ainda ser contratado em input.Split ( "()" ToCharArray ().) [1]
Prabhakaran

14
e no caso u quiser usar a mesma lógica para selecionar múltiplos:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE

1
cuidado para que este extracto solução salestambém a partir de cadeias de entrada contendo )sales(, (sales(etc
Stefano Spinucci

435

Uma maneira muito simples de fazer isso é usando expressões regulares:

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

Como resposta ao comentário (muito engraçado), aqui está o mesmo Regex com algumas explicações:

\(             # 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"

504
Adoro quando as pessoas dizem "uma maneira simples é usar expressões regulares" e depois oferecem o que equivale a uma série de hieróglifos indecifráveis ​​(é especialmente divertido quando pessoas diferentes sugerem regex e cada uma delas apresenta um conjunto diferente de hieróglifos para o mesmo problema ) :)
Deltics

47
Não há respostas suficientes na pilha que realmente expliquem o que está acontecendo. Obrigado pela maravilhosa explicação.
Sandy Gifford

Se você estiver usando '@' no início, acho que não precisa escapar dos parênteses?
rank1

10
@ rank1 você deve escapar dos parênteses. O que o @ oferece aqui é que você não precisa escapar das barras invertidas. Portanto, sem o @, seria como "\\ (([^)] *) \\)").
Diadistis 28/11

Isso não lida bem com grupos aninhados. Alterado paravar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen

91

Supondo que você tenha apenas um par de parênteses.

string s = "User name (sales)";
int start = s.IndexOf("(") + 1;
int end = s.IndexOf(")", start);
string result = s.Substring(start, end - start);

7
iniciar + 1 na substring é mais correto, se você quiser "vendas" em vez de (vendas)
Joze

1
o que acontecerá s = "Nome do usuário) (Vendas)"?
dotnetstep

@dotnetstep você está certo deveria estar int end = s.IndexOf(")", start);. Eu enfileirei uma edição ...
ChrisD 21/02

1
"(" .Length; é melhor que +1. Enviou uma edição. Também adicionou uma função.
Ave

24

Use esta função:

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

e aqui está o uso:

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

e a saída seria:

sales

16

Expressões regulares podem ser a melhor ferramenta aqui. Se você não tem familiaridade com eles, recomendo que você instale o Expresso - uma excelente ferramenta de regex.

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

14
string input = "User name (sales)";

string output = input.Substring(input.IndexOf('(') + 1, input.IndexOf(')') - input.IndexOf('(') - 1);

1
Obviamente, você deve calcular apenas a localização do primeiro colchete uma vez.
Martin Brown

No caso de você ter parênteses internos, por exemplo, input = "User name (sales(1))convém usar o input.LastIndexOf(')')que funcionará se houver parênteses interno ou não.
Ben

13

Um regex talvez? Eu acho que isso iria funcionar ...

\(([a-z]+?)\)

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

4

Use uma expressão regular:

string test = "(test)"; 
string word = Regex.Match(test, @"\((\w+)\)").Groups[1].Value;
Console.WriteLine(word);

4
int start = input.IndexOf("(") + 1;
int length = input.IndexOf(")") - start;
output = input.Substring(start, length);

2
input.Remove(input.IndexOf(')')).Substring(input.IndexOf('(') + 1);

2

O regexmétodo é superior, eu acho, mas se você quiser usar o 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);

ou

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

1

Aqui está uma função legível de uso geral que evita o uso de regex:

// 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 chamá-lo em seu exemplo específico, você pode fazer:

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

1

Estou descobrindo que expressões regulares são extremamente úteis, mas muito difíceis de escrever. Então, eu fiz algumas pesquisas e encontrei essa ferramenta que facilita a escrita deles.

Não se coíbe deles, porque é difícil descobrir a sintaxe. Eles podem ser tão poderosos.


2
Bem-vindo ao SO! Esse é um bom conselho, mas não deveria ter sido postado como resposta. Recomendações gerais como essa devem ser postadas como comentários, se houver. Uma resposta deve abordar o problema específico do solicitante. Sei que você ainda não tem pontos de reputação suficientes para postar comentários, mas é exatamente por isso que o limite de representantes existe. Quando você tiver um pouco mais de tempo, verá que as pessoas estão sempre recomendando ferramentas como o Rubular (nos comentários, é claro). Em outras palavras, esse conselho pode ser útil, mas não é urgente.
Alan Moore

0

Me deparei com isso enquanto procurava uma solução para uma implementação muito semelhante.

Aqui está um trecho do meu código real. Inicia a substring do primeiro caractere (índice 0).

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

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

 output = input.Substring(0, input.IndexOf(separator)); 

Isso não responde ao que o OP pediu.
Dicemaster 12/07/19

0

Esse código é mais rápido do que a maioria das soluções aqui (se não todas), compactado como método de extensão String , não suporta aninhamento 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 é um pouco mais longo e mais lento, mas lida com aninhamento recursivo de maneira mais agradável:

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