Как извлечь текст из круглых скобок?

183

У меня есть строка User name (sales), и я хочу извлечь текст между скобками, как бы это сделать?

Я подозреваю подстроку, но не могу понять, как читать до закрывающей скобки, длина текста будет меняться.

  • 2
    Покажите нам, что вы пытались. Вы смотрели на использование регулярных выражений?
Теги:

17 ответов

404

Очень простой способ сделать это - использовать регулярные выражения:

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

Как ответ на (очень смешной) комментарий, здесь одно и то же Regex с некоторым объяснением:

\(             # 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"
  • 461
    Мне нравится, когда люди говорят, что «простой способ - использовать регулярные выражения», а затем предлагают то, что составляет строку неразборчивых иероглифов (особенно забавно, когда разные люди предлагают регулярное выражение, и каждый из них предлагает свой набор иероглифов для одной и той же проблемы. ). :)
  • 41
    В стеке недостаточно ответов, которые на самом деле объясняют, что происходит. Спасибо за чудесное объяснение.
Показать ещё 6 комментариев
382

Если вы хотите держаться подальше от регулярных выражений, самым простым способом я могу подумать:

string input = "User name (sales)";
string output = input.Split('(', ')')[1];
  • 85
    Честно говоря, это должно было быть выбрано в качестве ответа.
  • 1
    Разве это не будет дополнительно заключено в input.Split ("()". ToCharArray ()) [1]
Показать ещё 1 комментарий
86

Предполагая, что у вас есть только одна пара скобок.

string s = "User name (sales)";
int start = s.IndexOf("(") + 1;
int end = s.IndexOf(")", start);
string result = s.Substring(start, end - start);
  • 7
    начало + 1 в подстроке правильнее, если вы хотите «продажи» вместо (продажи)
  • 1
    что произойдет с s = "User) name (Sales)"?
Показать ещё 2 комментария
23

Используйте эту функцию:

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

и вот использование:

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

и выход будет:

sales
14

Регулярные выражения могут быть лучшим инструментом здесь. Если вы не знакомы с ними, я рекомендую вам установить Expresso - отличный инструмент для регулярных выражений.

Что-то вроде:

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

string output = input.Substring(input.IndexOf('(') + 1, input.IndexOf(')') - input.IndexOf('(') - 1);
  • 1
    Конечно, вы должны рассчитать местоположение первой скобки только один раз.
  • 0
    Если у вас есть внутренняя скобка, например, input = "User name (sales(1)) вы можете использовать input.LastIndexOf(')') который будет работать, если есть внутренняя скобка или нет.
13
Возможно, существует регулярное выражение? Я думаю, что это сработает...
\(([a-z]+?)\)
5
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

Используйте регулярное выражение:

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

Метод regex превосходен, я думаю, но если вы хотите использовать скромный 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);

или

string input = "my name is (Jayne C)";
string output  = input.Substring(input.IndexOf("(") +1, input.IndexOf(")")- input.IndexOf("(")- 1);
2
input.Remove(input.IndexOf(')')).Substring(input.IndexOf('(') + 1);
0
int start = input.IndexOf("(") + 1;
int length = input.IndexOf(")") - start;
output = input.Substring(start, length);
0

Этот код быстрее, чем большинство решений здесь (если не все), упакован как String метод расширения, он не поддерживает рекурсивную вложенность:

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

Этот бит немного длиннее и медленнее, но он лучше справляется с рекурсивным вложением:

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

Я нахожу, что регулярные выражения чрезвычайно полезны, но очень трудно писать. Итак, я провел некоторое исследование и нашел это инструмент, который делает их очень легким.

Не уклоняйтесь от них, потому что синтаксис трудно понять. Они могут быть настолько мощными.

  • 2
    Добро пожаловать на ТАК! Это хороший совет, но его не следовало публиковать в качестве ответа. Общие советы, подобные этому, следует публиковать в виде комментариев, если они вообще есть. Ответ должен адресовать конкретную проблему спрашивающего. Я знаю, что у вас недостаточно очков репутации, чтобы оставлять комментарии, но именно поэтому существует порог повторения. Пройдя немного дольше, вы увидите, что люди всегда рекомендуют такие инструменты, как Rubular (в комментариях, конечно). Другими словами, этот совет может быть полезен, но это не срочно.
0

Я столкнулся с этим, когда искал решение для очень похожей реализации.

Вот фрагмент моего фактического кода. Запускает подстроку из первого char (индекс 0).

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

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

 output = input.Substring(0, input.IndexOf(separator)); 
  • 0
    Это не отвечает на то, что спросил ОП.
0

Вот универсальная читаемая функция, которая позволяет избежать использования регулярного выражения:

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

Чтобы вызвать его в своем конкретном примере, вы можете:

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

Это похоже на некоторые из приведенных выше ответов, но не использует регулярное выражение и представляет собой простой способ копирования и вставки для вас:

public String getSubstring(String startChar, String endChar, String initString)
{
    return initString.substring((initString.indexOf(startChar) + 1), (initString.indexOf(endChar)));
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню