我有一个字符串用户名(销售),我想提取括号之间的文本,我该如何做到这一点?

我怀疑子字符串,但我不知道如何阅读,直到右括号,文本的长度会有所不同。


当前回答

我认为regex方法更好,但如果你想使用卑微的子字符串

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

or

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

其他回答

这段代码比这里的大多数解决方案(如果不是全部的话)都快,打包为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;
}

也许是正则表达式?我认为这行得通……

\(([a-z]+?)\)

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

如果你想远离正则表达式,我能想到的最简单的方法是:

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

我最近一直在使用和滥用c# 9,甚至在一些可疑的场景中,我也忍不住要加入span…只是为了好玩,以下是上述答案的变体:

var input = "User name (sales)";
var txtSpan = input.AsSpan();
var startPoint = txtSpan.IndexOf('(') + 1;
var length = txtSpan.LastIndexOf(')') - startPoint;
var output = txtSpan.Slice(startPoint, length);

对于OP的特定场景,它产生正确的输出。 (就我个人而言,我会使用其他人发布的RegEx。在上述解决方案崩溃的情况下,更容易解决更棘手的情况)。

我为自己的项目做了一个更好的版本(作为扩展方法):

//Note: This only captures the first occurrence, but 
//can be easily modified to scan across the text (I'd prefer Slicing a Span)  
public static string ExtractFromBetweenChars(this string txt, char openChar, char closeChar)
{
    ReadOnlySpan<char> span = txt.AsSpan();
    int firstCharPos = span.IndexOf(openChar);
    int lastCharPos = -1;

    if (firstCharPos != -1) 
    { 
        for (int n = firstCharPos + 1; n < span.Length; n++)
        {
            if (span[n] == openChar) firstCharPos = n; //This allows the opening char position to change
            if (span[n] == closeChar) lastCharPos = n;
            if (lastCharPos > firstCharPos) break;
            //This would correctly extract "sales" from this [contrived]
            //example: "just (a (name (sales) )))(test"
        }
        return span.Slice(firstCharPos + 1, lastCharPos - firstCharPos - 1).ToString();
    }
    return "";
}