Jak wyodrębnić tekst między nawiasami okrągłymi (nawiasy okrągłe)?


224

Mam ciąg User name (sales)i chcę wyodrębnić tekst między nawiasami, jak mam to zrobić?

Podejrzewam ciąg podrzędny, ale nie potrafię czytać, dopóki nie zostanie zamknięty nawias, długość tekstu będzie się różnić.


2
Pokaż nam, co próbowałeś. Czy zastanawiałeś się nad użyciem wyrażeń regularnych?
George Stocker,

Odpowiedzi:


445

Jeśli chcesz trzymać się z dala od wyrażeń regularnych, najprostszym sposobem, jaki mogę wymyślić, jest:

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

91
Szczerze mówiąc, powinno to zostać wybrane jako odpowiedź.
Pat Lindley,

1
Czy nie będzie dalej zawężany do input.Split („()”. ToCharArray ()) [1]
prabhakaran

14
a jeśli chcesz użyć tej samej logiki, aby wybrać wiele:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE 25.04.16

1
pamiętaj, że ten ekstrakt rozwiązanie salestakże z ciągów wejściowych zawierających )sales(, (sales(etc
Stefano Spinucci

435

Bardzo prostym sposobem na to jest użycie wyrażeń regularnych:

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

W odpowiedzi na (bardzo zabawny) komentarz, oto ten sam Regex z wyjaśnieniem:

\(             # 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
Uwielbiam to, gdy ludzie mówią: „prostym sposobem jest użycie wyrażeń regularnych”, a następnie oferują to, co stanowi ciąg nieczytelnych hieroglifów (jest to szczególnie zabawne, gdy różni ludzie sugerują wyrażenia regularne i każdy z nich ma inny zestaw hieroglifów dla tego samego problemu ). :)
Deltics

47
Na stosie nie ma wystarczającej liczby odpowiedzi, które faktycznie wyjaśniają, co się dzieje. Dziękuję za cudowne wyjaśnienie.
Sandy Gifford

Jeśli używasz „@” na początku, myślę, że nie musisz uciec od nawiasu?
ranga 1

10
@ rank1 musisz uciec od nawiasu. @ Oferuje tutaj to, że nie musisz uciekać przed ukośnikami. Więc bez @ byłoby to jak „\\ (([^)] *) \\)”.
Diadistis,

Nie radzi sobie to jednak dobrze z grupami zagnieżdżonymi. Zmieniono navar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen,

91

Zakładając, że masz tylko jedną parę nawiasów.

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 w podciągu jest bardziej poprawny, jeśli chcesz „sprzedaży” zamiast (sprzedaży)
Joze

1
co się stanie s = „nazwa użytkownika” (sprzedaż)?
dotnetstep

@dotnetstep masz rację int end = s.IndexOf(")", start);. Mam w kolejce edycję ...
ChrisD

1
„(„ .Length; jest lepszy niż +1. Wysłał edycję. Dodano także funkcję.
Ave

24

Użyj tej funkcji:

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

a oto użycie:

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

i wynik byłby:

sales

16

Wyrażenia regularne mogą być tutaj najlepszym narzędziem. Jeśli nie jesteś z nimi zaznajomiony, zalecamy zainstalowanie Expresso - świetnego małego narzędzia do wyrażania regularnego.

Coś jak:

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
Oczywiście należy tylko raz obliczyć lokalizację pierwszego nawiasu.
Martin Brown,

W przypadku, gdy masz wewnętrzny nawias, np. input = "User name (sales(1))Możesz chcieć użyć tego, input.LastIndexOf(')')który zadziała, jeśli istnieje wewnętrzny nawias lub nie.
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

Użyj wyrażenia regularnego:

string test = "(test)"; 
string word = Regex.Match(test, @"\((\w+)\)").Groups[1].Value;
Console.WriteLine(word);



2

regexMetoda jest lepsza myślę, ale jeśli chciał użyć pokornychsubstring

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

lub

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

1

Oto funkcja ogólnego przeznaczenia, która pozwala uniknąć wyrażeń regularnych:

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

Aby nazwać to w konkretnym przykładzie, możesz:

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

1

Uważam, że wyrażenia regularne są niezwykle przydatne, ale bardzo trudne do napisania. Przeprowadziłem badania i znalazłem to narzędzie, które sprawia, że ​​pisanie ich jest tak łatwe.

Nie wahaj się przed nimi, ponieważ trudno jest zrozumieć składnię. Mogą być tak potężni.


2
Witamy w SO! To dobra rada, ale nie powinna być opublikowana jako odpowiedź. Takie ogólne porady powinny być zamieszczane jako komentarze, jeśli w ogóle. Odpowiedź musi dotyczyć konkretnego problemu pytającego. Wiem, że nie masz jeszcze wystarczającej liczby punktów reputacji, aby dodawać komentarze, ale właśnie dlatego istnieje próg rep. Gdy będziesz już trochę dłużej, zobaczysz, że ludzie zawsze polecają narzędzia takie jak Rubular (oczywiście w komentarzach). Innymi słowy, ta rada może być przydatna, ale nie jest pilna.
Alan Moore

0

Natknąłem się na to, kiedy szukałem rozwiązania bardzo podobnej implementacji.

Oto fragment mojego faktycznego kodu. Rozpoczyna podciąg od pierwszego znaku (indeks 0).

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

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

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

To nie odpowiada na pytania OP.
dicemaster,

0

Ten kod jest szybszy niż większość dostępnych tutaj rozwiązań (jeśli nie wszystkie), spakowany jako metoda rozszerzenia String , nie obsługuje zagnieżdżania rekurencyjnego:

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

Ten jest trochę dłuższy i wolniejszy, ale ładniej radzi sobie z zagnieżdżaniem rekurencyjnym:

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;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.