Comment extraire du texte entre parenthèses (crochets)?

224

J'ai une chaîne User name (sales)et je souhaite extraire le texte entre crochets, comment dois-je procéder?

Je soupçonne une sous-chaîne, mais je ne peux pas savoir comment lire jusqu'à ce que le crochet de fermeture, la longueur du texte varie.

gotqn
la source
2
Montrez-nous ce que vous avez essayé. Avez-vous envisagé d'utiliser des expressions régulières?
George Stocker

Réponses:

445

Si vous souhaitez vous éloigner des expressions régulières, la façon la plus simple à laquelle je peux penser est:

string input = "User name (sales)";
string output = input.Split('(', ')')[1];
Jelly Ama
la source
91
Honnêtement, cela aurait dû être sélectionné comme réponse.
Pat Lindley
1
N'est-il pas plus contracté en entrée.Split ("()". ToCharArray ()) [1]
prabhakaran
14
et dans le cas où vous souhaitez utiliser la même logique pour sélectionner plusieurs:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE
1
méfiez-vous que cette solution extrait saleségalement des chaînes d'entrée contenant )sales(, (sales(etc.
Stefano Spinucci
435

Une façon très simple de le faire est d'utiliser des expressions régulières:

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

En réponse au commentaire (très drôle), voici le même Regex avec quelques explications:

\(             # 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
la source
504
J'adore quand les gens disent "un moyen simple consiste à utiliser des expressions régulières" et offrent ensuite ce qui équivaut à une chaîne de hiéroglyphes indéchiffrables (c'est particulièrement amusant lorsque différentes personnes suggèrent l'expression régulière et chacune propose un ensemble différent de hiéroglyphes pour le même problème ). :)
Deltics
47
Il n'y a pas assez de réponses sur la pile qui expliquent réellement ce qui se passe. Merci pour la merveilleuse explication.
Sandy Gifford
Si vous utilisez '@' au début, je pense que vous n'avez pas besoin d'échapper à la parenthèse?
rank1
10
@ rank1 vous devez échapper à la parenthèse. Ce que @ propose ici, c'est que vous n'avez pas besoin d'échapper aux barres obliques inverses. Donc, sans le @, ce serait comme "\\ (([^)] *) \\)".
Diadistis
Cependant, cela ne gère pas bien les groupes imbriqués. Changé pourvar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen
91

En supposant que vous n'avez qu'une seule paire de parenthèses.

string s = "User name (sales)";
int start = s.IndexOf("(") + 1;
int end = s.IndexOf(")", start);
string result = s.Substring(start, end - start);
Ross Goddard
la source
7
start + 1 dans la sous-chaîne est plus correct si vous voulez "sales" au lieu de (sales)
Joze
1
que va-t-il arriver s = "Nom d'utilisateur (Ventes)"?
dotnetstep
@dotnetstep vous avez raison devrait l'être int end = s.IndexOf(")", start);. J'ai mis en file d'attente un montage ...
ChrisD
1
"(" .Longueur; vaut mieux que +1. Envoyé une modification. Également ajouté une fonction.
Ave
24

Utilisez cette fonction:

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

et voici l'utilisation:

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

et la sortie serait:

sales
artfulhacker
la source
16

Les expressions régulières pourraient être le meilleur outil ici. Si vous ne les connaissez pas, je vous recommande d'installer Expresso , un excellent petit outil d'expression régulière.

Quelque chose comme:

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
la source
14
string input = "User name (sales)";

string output = input.Substring(input.IndexOf('(') + 1, input.IndexOf(')') - input.IndexOf('(') - 1);
Nick Allen
la source
1
Bien entendu, vous ne devez calculer l'emplacement du premier support qu'une seule fois.
Martin Brown
Dans le cas où vous avez des parenthèses internes, par exemple, input = "User name (sales(1))vous pouvez utiliser input.LastIndexOf(')')ce qui fonctionnera s'il y a des parenthèses internes ou non.
Ben
13

Un regex peut-être? Je pense que cela fonctionnerait ...

\(([a-z]+?)\)
frissons42
la source
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
la source
4

Utilisez une expression régulière:

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

La regexméthode est supérieure je pense, mais si vous vouliez utiliser l'humblesubstring

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);
en dépit
la source
1

Voici une fonction lisible à usage général qui évite d'utiliser l'expression régulière:

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

Pour l'appeler dans votre exemple particulier, vous pouvez faire:

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

Je trouve que les expressions régulières sont extrêmement utiles mais très difficiles à écrire. J'ai donc fait quelques recherches et trouvé cet outil qui les rend si faciles à écrire.

Ne vous éloignez pas d'eux car la syntaxe est difficile à comprendre. Ils peuvent être si puissants.

katyholb
la source
2
Bienvenue chez SO! C'est un bon conseil, mais il n'aurait pas dû être publié comme réponse. Des conseils généraux comme celui-ci devraient être affichés sous forme de commentaires, le cas échéant. Une réponse doit répondre au problème spécifique du demandeur. Je sais que vous n'avez pas encore assez de points de réputation pour publier des commentaires, mais c'est exactement pourquoi le seuil de répétition existe. Lorsque vous resterez un peu plus longtemps, vous verrez que les gens recommandent toujours des outils comme Rubular (dans les commentaires, bien sûr). En d'autres termes, ces conseils peuvent être utiles, mais ils ne sont pas urgents.
Alan Moore
0

Je suis tombé sur cela alors que je cherchais une solution pour une implémentation très similaire.

Voici un extrait de mon code actuel. Démarre la sous-chaîne à partir du premier caractère (index 0).

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

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

 output = input.Substring(0, input.IndexOf(separator)); 
nikk
la source
Cela ne répond pas à ce que le PO a demandé.
dicemaster
0

Ce code est plus rapide que la plupart des solutions ici (sinon toutes), compressé en tant que méthode d'extension de chaîne , il ne prend pas en charge l'imbrication récursive:

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

Celui-ci est un peu plus long et plus lent, mais il gère mieux l'imbrication récursive:

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
la source