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.


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

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"

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

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

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

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

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

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]+?)\)

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

Utilisez une expression régulière:

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

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

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)", "(", ")");

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.


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

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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.