Wie extrahiere ich Text, der zwischen Klammern steht (runde Klammern)?


224

Ich habe eine Zeichenfolge User name (sales)und möchte den Text zwischen den Klammern extrahieren. Wie würde ich das tun?

Ich vermute eine Teilzeichenfolge, kann aber erst in der schließenden Klammer herausfinden, wie sie gelesen werden soll. Die Textlänge variiert.


2
Zeigen Sie uns, was Sie versucht haben. Haben Sie sich die Verwendung regulärer Ausdrücke angesehen?
George Stocker

Antworten:


445

Wenn Sie sich von regulären Ausdrücken fernhalten möchten, ist der einfachste Weg, den ich mir vorstellen kann:

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

91
Ehrlich gesagt hätte dies als Antwort ausgewählt werden sollen.
Pat Lindley

1
Wird es nicht weiter in input.Split ("()". ToCharArray ()) [1]
prabhakaran

14
und falls Sie dieselbe Logik verwenden möchten, um mehrere auszuwählen:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE

1
Beachten Sie, dass diese Lösung salesauch aus Eingabezeichenfolgen extrahiert )sales(, die (sales(usw. enthalten
Stefano Spinucci

434

Eine sehr einfache Möglichkeit ist die Verwendung regulärer Ausdrücke:

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

Als Antwort auf den (sehr lustigen) Kommentar hier derselbe Regex mit einigen Erklärungen:

\(             # 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
Ich finde es toll, wenn Leute sagen, "eine einfache Möglichkeit ist es, reguläre Ausdrücke zu verwenden" und dann eine Reihe von nicht entzifferbaren Hieroglyphen anbieten (es macht besonders Spaß, wenn verschiedene Leute Regex vorschlagen und jeder einen anderen Satz von Hieroglyphen für das gleiche Problem entwickelt ). :)
Deltics

47
Es gibt nicht annähernd genug Antworten auf dem Stapel, die tatsächlich erklären, was los ist. Vielen Dank für die wunderbare Erklärung.
Sandy Gifford

Wenn Sie zu Beginn '@' verwenden, müssen Sie sich nicht der Klammer entziehen?
Rang 1

10
@ rank1 müssen Sie die Klammer verlassen. Was @ hier bietet, ist, dass Sie den Backslashes nicht entkommen müssen. Ohne das @ wäre es also "\\ (([^)] *) \\)".
Diadistis

Dies behandelt verschachtelte Gruppen jedoch nicht gut. Geändert zuvar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen

91

Angenommen, Sie haben nur ein Klammerpaar.

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 in der Teilzeichenfolge ist korrekter, wenn Sie "Verkäufe" anstelle von (Verkäufe) wollen
Joze

1
Was passiert mit s = "Benutzer) Name (Vertrieb)"?
Dotnetstep

@dotnetstep du hast recht sollte sein int end = s.IndexOf(")", start);. Ich habe eine Bearbeitung in die Warteschlange gestellt ...
ChrisD

1
"(" .Length; ist besser als +1. Hat eine Bearbeitung gesendet. Außerdem wurde eine Funktion hinzugefügt.
Ave

24

Verwenden Sie diese Funktion:

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

und hier ist die Verwendung:

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

und die Ausgabe wäre:

sales

16

Reguläre Ausdrücke könnten hier das beste Werkzeug sein. Wenn Sie mit ihnen nicht vertraut sind, empfehle ich Ihnen, Expresso zu installieren - ein großartiges kleines Regex-Tool.

Etwas wie:

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
Sie sollten die Position der ersten Klammer natürlich nur einmal berechnen.
Martin Brown

In dem Fall, in dem Sie eine innere Klammer haben input = "User name (sales(1)), möchten Sie möglicherweise eine verwenden, input.LastIndexOf(')')die funktioniert, wenn eine innere Klammer vorhanden ist oder nicht.
Ben


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

Verwenden Sie einen regulären Ausdruck:

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

Die regexMethode ist meiner Meinung nach überlegen, aber wenn Sie die bescheidenen verwenden wolltensubstring

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

oder

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

1

Hier ist eine allgemein lesbare Funktion, die die Verwendung von Regex vermeidet:

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

Um es in Ihrem speziellen Beispiel zu nennen, können Sie Folgendes tun:

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

1

Ich finde, dass reguläre Ausdrücke äußerst nützlich, aber sehr schwer zu schreiben sind. Also habe ich einige Nachforschungen angestellt und dieses Tool gefunden , das das Schreiben so einfach macht.

Scheuen Sie sich nicht vor ihnen, denn die Syntax ist schwer herauszufinden. Sie können so mächtig sein.


2
Willkommen bei SO! Dies ist ein guter Rat, der jedoch nicht als Antwort hätte veröffentlicht werden dürfen. Allgemeine Ratschläge wie diese sollten, wenn überhaupt, als Kommentare veröffentlicht werden. Eine Antwort muss das spezifische Problem des Fragestellers ansprechen. Ich weiß, dass Sie noch nicht genügend Reputationspunkte haben, um Kommentare zu veröffentlichen, aber genau aus diesem Grund gibt es die Wiederholungsschwelle. Wenn Sie schon länger dabei sind, werden Sie feststellen, dass die Leute immer Tools wie Rubular empfehlen (natürlich in Kommentaren). Mit anderen Worten, dieser Rat mag nützlich sein, ist aber nicht dringend.
Alan Moore

0

Ich bin darauf gestoßen, als ich nach einer Lösung für eine sehr ähnliche Implementierung gesucht habe.

Hier ist ein Ausschnitt aus meinem aktuellen Code. Startet die Teilzeichenfolge ab dem ersten Zeichen (Index 0).

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

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

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

Dies beantwortet nicht, was das OP gefragt hat.
Dicemaster

0

Dieser Code ist schneller als die meisten Lösungen hier (wenn nicht alle) und als String- Erweiterungsmethode gepackt. Er unterstützt keine rekursive Verschachtelung:

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

Dieser ist etwas länger und langsamer, aber er handhabt rekursives Verschachteln besser:

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.