web-dev-qa-db-fra.com

Comment extraire le texte entre parenthèses (parenthèses)?

J'ai une chaîne User name (sales) et je souhaite extraire le texte entre crochets. Comment procéderais-je?

Je soupçonne une sous-chaîne mais je ne sais pas comment lire avant le crochet de fermeture, la longueur du texte pouvant varier.

214
Ben H

Un moyen 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 amusant), 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"
415
Diadistis

Si vous souhaitez vous éloigner des expressions régulières, voici la façon la plus simple de procéder:

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

En supposant que vous n’ayez qu’une 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);
92
Ross Goddard

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'usage:

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

et le résultat serait:

sales
24
artfulhacker

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

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

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

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

\(([a-z]+?)\)
13
chills42
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;
}
7
Bilal Mrad

Utilisez une expression régulière:

string test = "(test)"; 
string Word = Regex.Match(test, @"\((\w+)\)").Groups[1].Value;
Console.WriteLine(Word);
4
Will Dean
input.Remove(input.IndexOf(')')).Substring(input.IndexOf('(') + 1);
2
Rockcoder

La méthode regex est supérieure, je pense, mais si vous vouliez utiliser l'humble substring

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);
2
inspite
int start = input.IndexOf("(") + 1;
int length = input.IndexOf(")") - start;
output = input.Substring(start, length);
2

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 les craignez pas, car la syntaxe est difficile à comprendre. Ils peuvent être si puissants.

1
katyholb

Ce code est plus rapide que la plupart des solutions ici (si pas toutes), compressé sous la forme Stringméthode d'extension , 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 lent, mais il gère plus facilement 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;
}
0
watbywbarif

Voici une fonction lisible à des fins générales qui évite d’utiliser 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);
}

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

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

Je suis tombé sur cela alors que je cherchais une solution à 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)); 
0
nikk