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á.

gotqn
fonte
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];
Jelly Ama
fonte
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"
Diadistis
fonte
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);
Ross Goddard
fonte
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
artfulhacker
fonte
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;
}
Jennifer
fonte
14
string input = "User name (sales)";

string output = input.Substring(input.IndexOf('(') + 1, input.IndexOf(')') - input.IndexOf('(') - 1);
Nick Allen
fonte
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]+?)\)
calafrios42
fonte
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
fonte
4

Use uma expressão regular:

string test = "(test)"; 
string word = Regex.Match(test, @"\((\w+)\)").Groups[1].Value;
Console.WriteLine(word);
Will Dean
fonte
4
int start = input.IndexOf("(") + 1;
int length = input.IndexOf(")") - start;
output = input.Substring(start, length);
Gustavo Baiocchi Costa
fonte
2
input.Remove(input.IndexOf(')')).Substring(input.IndexOf('(') + 1);
Rockcoder
fonte
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);
Apesar
fonte
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)", "(", ")");
ChaimG
fonte
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.

katyholb
fonte
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)); 
nikk
fonte
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;
}
watbywbarif
fonte