如何从字符串中仅删除某些子字符串?

时间:2015-01-23 08:18:31

标签: c# regex string

使用C#,我有一个字符串,它是一个包含多个查询的SQL脚本。我想删除用单引号括起来的字符串部分。我可以使用Regex.Replace以这种方式执行此操作:

string test = "Only 'together' can we turn him to the 'dark side' of the Force";
test = Regex.Replace(test, "'[^']*'", string.Empty);

结果:"我们才能将他变成原力"

我想要做的是删除包含特定子字符串的子字符串的引号之间的子字符串EXCEPT。例如,使用上面的字符串,我想删除引用的子字符串,除了那些包含" dark,"这样得到的字符串是:

结果:"我们才能将他转向“黑暗面”'部队"

如何使用Regex.Replace或其他技术完成此操作?我目前正在尝试使用Substring()IndexOf()Contains()的解决方案。

注意:我不在乎单身是否引用"黑暗面"是否被移除,所以结果也可能是:"只有我们才能把他变成原力的黑暗面。"我这样说是因为使用Split()的解决方案会删除所有单引号。

修改:我还没有使用Substring()IndexOf()等解决方案。通过"继续工作,"我的意思是我在脑海里想着如何做到这一点。我没有代码,这就是为什么我还没有发布任何代码。感谢。

修改:VKS的解决方案可以解决问题。我没有逃脱\ b第一次尝试,这就是它失败的原因。此外,除非我在整个字符串中包含单引号,否则它不起作用。

test = Regex.Replace(test, "'(?![^']*\\bdark\\b)[^']*'", string.Empty);

5 个答案:

答案 0 :(得分:21)

'(?![^']*\bdark\b)[^']*'

试试这个。查看demo。替换empty string。您可以在此处使用lookahead来检查''是否包含单词dark

https://www.regex101.com/r/rG7gX4/12

答案 1 :(得分:16)

虽然vks的解决方案有效,但我想展示一种不同的方法:

string test = "Only 'together' can we turn him to the 'dark side' of the Force";
test = Regex.Replace(test, @"'[^']*'", match => {
    if (match.Value.Contains("dark"))
        return match.Value;

    // You can add more cases here

    return string.Empty;
});

或者,如果您的情况很简单:

test = Regex.Replace(test, @"'[^']*'", match => match.Value.Contains("dark")
    ? match.Value
    : string.Empty
);

也就是说,使用lambda为替换提供回调。这样,您可以运行任意逻辑来替换字符串。

答案 2 :(得分:4)

这样的事情会起作用。
你可以将想要保留的所有字符串添加到excludedStrings数组

        string test = "Only 'together' can we turn him to the 'dark side' of the Force";

        var excludedString = new string[] { "dark side" };

        int startIndex = 0;

        while ((startIndex = test.IndexOf('\'', startIndex)) >= 0)
        {
            var endIndex = test.IndexOf('\'', startIndex + 1);
            var subString = test.Substring(startIndex, (endIndex - startIndex) + 1);
            if (!excludedString.Contains(subString.Replace("'", "")))
            {
                test = test.Remove(startIndex, (endIndex - startIndex) + 1);
            }
            else
            {
                startIndex = endIndex + 1;
            }
        }

答案 3 :(得分:1)

我做了这个尝试,我认为你正在考虑(使用splitContain,...没有regex的某些解决方案)

string test = "Only 'together' can we turn him to the 'dark side' of the Force";
string[] separated = test.Split('\'');

string result = "";

for (int i = 0; i < separated.Length; i++)
{
    string str = separated[i];
    str = str.Trim();   //trim the tailing spaces

    if (i % 2 == 0 || str.Contains("dark")) // you can expand your condition
    {
       result += str+" ";  // add space after each added string
    }
}
result = result.Trim(); //trim the tailing space again

答案 4 :(得分:1)

通过正则表达式交替运算符|的另一种方法。

@"('[^']*\bdark\b[^']*')|'[^']*'"

然后将匹配的字符替换为$1

DEMO

string str = "Only 'together' can we turn him to the 'dark side' of the Force";
string result = Regex.Replace(str, @"('[^']*\bdark\b[^']*')|'[^']*'", "$1");
Console.WriteLine(result);

IDEONE

<强>解释

  • (...)名为capturing group

  • '[^']*\bdark\b[^']*'将匹配包含子字符串dark的所有单引号字符串。 [^']*匹配任何字符,但不匹配',零次或多次。

  • ('[^']*\bdark\b[^']*'),因为正则表达式位于捕获组内,所有匹配的字符都存储在组索引1中。

  • |接下来是正则表达式alternation operator

  • '[^']*'现在,这与所有剩余(除了包含dark个)的单引号字符串相匹配。请注意,这不会匹配包含子字符串dark的单引号字符串,因为我们已经将这些字符串与之前存在的模式匹配到|交替运算符。

  • 最后用组索引1中的字符替换所有匹配的字符将为您提供所需的输出。