C# 如何仅在整个文本被括号包围时删除括号?

C# 如何仅在整个文本被括号包围时删除括号?,c#,.net,regex,string,C#,.net,Regex,String,我只想在整个文本被括号包围时删除括号。例如: (text (text) text) 需要转换为: text (text) text 我有一个非常简单的检查: value = (value [0] == '(' && value [value .Length - 1] == ')') ? value.Substring(1, value .Length - 2) : value; 但它失败并错误地删除了这类字符串的括号: (text (text) ) text (text)

我只想在整个文本被括号包围时删除括号。例如:

(text (text) text)
需要转换为:

text (text) text
我有一个非常简单的检查:

value = (value [0] == '(' && value [value .Length - 1] == ')') ? value.Substring(1, value .Length - 2) : value;
但它失败并错误地删除了这类字符串的括号:

(text (text) ) text (text)
有谁能告诉我一种处理所有案件的方法吗?使用正则表达式也是正常的

请注意,括号是平衡的。例如,这种情况是不可能的:

( text ( text )

这种扩展方法应该有效

public static class StringExtensions
{
    public static string RemoveParentheses(this string value)
    {
        if (value == null || value[0] != '(' || value[value.Length - 1 ] != ')') return value;

        var cantrim = false;
        var openparenthesesIndex = new Stack<int>();
        var count = 0;
        foreach (char c in value)
        {
            if (c == '(')
            {
                openparenthesesIndex.Push(count);
            }
            if (c == ')')
            {
                cantrim = (count == value.Length - 1 && openparenthesesIndex.Count == 1 && openparenthesesIndex.Peek() == 0);
                openparenthesesIndex.Pop();
            }
            count++;
        }

        if (cantrim)
        {
            return value.Trim(new[] { '(', ')' });
        }
        return value;
    }
}

使用一个简单的循环进行测试,如果它对删除“有效”,请删除第一个和最后一个:

bool isValid = value[0] == '(' && value[value.Length - 1] == ')';
int i = 1;
int c = 0;
for(; isValid && c >= 0 && i < value.Length - 1; i++)
{
  if(value[i] == '(')
    c++;
  else if(value[i] == ')')
    c--;
}

if(isValid && i == (value.Length - 1) && c == 0)
  value = value.Substring(1, value.Length - 2);
bool isValid=value[0]='('&&value[value.Length-1]=');
int i=1;
int c=0;
对于(;isValid&&c>=0&&i
运行了一些测试用例,我认为这很好

public string CleanString(string CleanMe)
{
    if (string.IsNullOrEmpty(CleanMe)) return CleanMe;
    string input = CleanMe.Trim();
    if (input.Length <= 2) return input;
    if (input[0] != '(') return input;
    if (input[input.Length-1] != ')') return input;
    int netParen = 1;  // starting loop at 1 have one paren already
    StringBuilder sb = new StringBuilder();
    for (int i = 1; i < input.Length-1; i++)
    {
        char c = input[i];
        sb.Append(c);
        if (c == '(') netParen++;
        else if (c == ')') netParen--;
        if (netParen == 0) return input;  // this is the key did the () get closed out
    }
    return sb.ToString();
}
publicstringcleanstring(stringcleanme)
{
if(string.IsNullOrEmpty(CleanMe))返回CleanMe;
字符串输入=CleanMe.Trim();

如果(input.Length)在您的失败案例中,“整个文本”没有被括号包围,这显然是您想要解决的问题,您能否重申您试图解决的问题?您的示例中的
文本是否包含空格?正则表达式不适用于此。它缺乏解析和“记住”的能力上下文。但是使用循环非常简单。你也有(text(text))(text(text))(我认为)你能做的最好的事情就是使用foreach(chac-in-string)然后将每一个都映射到一个打开的位置,最后一个将与第一个匹配,否则它就错了。
i
c
都应该从0开始。另外,当
c
等于0时,必须断开循环。(在循环结束时检查
c==0
)@M.kazemAkhgary-不,他们不应该…i=0已经过验证,正如Eric刚才建议的,它甚至可以通过检查最后一个字符来改进。@M.kazemAkhgary:我不理解你的评论;第一个字符已经通过检查
的初始化isValid
来处理。如果它是真的,那么就有一个字符已处理,计数为一个开放参数。此外,代码在循环条件下会检查c是否等于零。这是一个非负数,因此检查它是否大于零就足够了。这现在正在工作。但最好从1开始
c
,并在c=0时中断循环。这更有意义。@M.kazemAkhgary-我不知道我认为这样或那样做很“有意义”。它应该简单且有效。计数是针对所有括号,还是仅针对外部括号内的括号(因此负数是非法的)没有区别。
public string CleanString(string CleanMe)
{
    if (string.IsNullOrEmpty(CleanMe)) return CleanMe;
    string input = CleanMe.Trim();
    if (input.Length <= 2) return input;
    if (input[0] != '(') return input;
    if (input[input.Length-1] != ')') return input;
    int netParen = 1;  // starting loop at 1 have one paren already
    StringBuilder sb = new StringBuilder();
    for (int i = 1; i < input.Length-1; i++)
    {
        char c = input[i];
        sb.Append(c);
        if (c == '(') netParen++;
        else if (c == ')') netParen--;
        if (netParen == 0) return input;  // this is the key did the () get closed out
    }
    return sb.ToString();
}