如何提取括号(圆括号)之间的文本?


224

我有一个字符串User name (sales),我想提取方括号之间的文本,我该怎么做?

我怀疑是子字符串,但是直到右括号之前,我无法弄清楚如何阅读,文本的长度会有所不同。


2
向我们展示您的尝试。您是否看过使用正则表达式?
George Stocker

Answers:


445

如果您希望远离正则表达式,那么我想到的最简单的方法是:

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

91
老实说,应该选择它作为答案。
Pat Lindley

1
是不是进一步收缩到input.Split(“()”。ToCharArray())[1]
prabhakaran 2014年

14
并且如果您想使用相同的逻辑来选择多个:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE

1
提防此溶液提取物sales也从输入串含有)sales((sales(等等
斯特凡诺Spinucci

435

一种非常简单的方法是使用正则表达式:

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

作为对(非常有趣的)评论的回应,这是同一个正则表达式,带有一些解释:

\(             # 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
当人们说“一种简单的方法是使用正则表达式”然后提供相当于无法理解的象形文字的字符串时,我会喜欢上它(当不同的人建议使用正则表达式并且每个人针对同一问题提出不同的象形文字时,这特别有趣。 )。:)
Deltics 2010年

47
实际上,堆栈上没有足够的答案来解释发生了什么。 谢谢您的精彩解释。
桑迪·吉福德

如果您在一开始使用“ @”,我认为您不需要转括号吗?
13年

10
@ rank1,您必须转义括号。@提供的是您不需要转义反斜杠。因此,如果没有@,它将类似于“ \\(([[^)] *)\\)”。
Diadistis

但是,这不能很好地处理嵌套组。更改为var filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen '16

91

假设您只有一对括号。

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更正确
-Joze

1
s =“用户名(销售)”会发生什么?
dotnetstep

@dotnetstep你是对的int end = s.IndexOf(")", start);。我已经排队进行编辑了……
ChrisD

1
“(”。长度;大于+1更好地发送一个修改还增加了一个功能。
大道

24

使用此功能:

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

16

正则表达式可能是这里最好的工具。如果您不熟悉它们,建议您安装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;
}

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

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

1
当然,您应该只计算一次第一个支架的位置。
马丁·布朗

例如,如果您有内部括号input = "User name (sales(1)),则可能需要使用input.LastIndexOf(')')是否有内部括号的方法。
2015年

13

正则表达式?我认为这行得通...

\(([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

使用正则表达式:

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

1

这是避免使用正则表达式的通用可读函数:

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

1

我发现正则表达式非常有用,但很难编写。因此,我进行了一些研究,发现此工具使编写它们变得如此容易。

不要回避它们,因为语法很难弄清楚。它们可以如此强大。


2
欢迎来到SO!这是一个很好的建议,但不应将其发布为答案。如果有的话,这样的一般性建议应以评论的形式发布。答案必须解决询问者的特定问题。我知道您的信誉点尚不足以发表评论,但这就是为什么存在代表阈值的原因。当您待了一段时间后,您会发现人们总是在推荐像Rubular这样的工具(当然是在评论中)。换句话说,此建议可能有用,但并不紧急。
艾伦·摩尔

0

我在寻找非常相似的实现方案的解决方案时遇到了这个问题。

这是我的实际代码片段。从第一个字符(索引0)开始。

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

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

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

这不能回答OP的要求。
dicemaster

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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.