【问题标题】:How to remove only certain substrings from a string?如何从字符串中仅删除某些子字符串?
【发布时间】:2015-01-23 08:18:30
【问题描述】:

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

结果:“我们只能把他变成原力”

我想要做的是删除引号之间的子字符串,除了包含特定子字符串的子字符串。例如,使用上面的字符串,我想删除带引号的子字符串,除了那些包含“dark”的子字符串,这样生成的字符串是:

结果:“只有我们才能把他变成原力的‘黑暗面’”

如何使用Regex.Replace 或通过其他技术来实现?我目前正在尝试使用Substring()IndexOf()Contains() 的解决方案。

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

编辑:我还没有使用Substring()IndexOf() 等的解决方案。通过“工作”,我的意思是我在脑海中思考这怎么可能完毕。我没有代码,这就是为什么我还没有发布任何代码。谢谢。

编辑:以下 VKS 的解决方案有效。我没有逃避 \b 第一次尝试,这就是它失败的原因。此外,除非我在整个字符串周围加上单引号,否则它也不起作用。

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

【问题讨论】:

  • @AndyKorneyev 是什么让您认为这不是在这里提问的好方法?这是我一段时间以来看到的最完整的第一篇文章。有一个很好的尝试,使用正则表达式,问题很清楚,有一些想法,我真的不知道这怎么可能更好,更不用说包括实际答案了。
  • @AndyKorneyev Op 的两行代码显示了他的努力,不是吗?此外,这个问题写得很好,显示出非常好的研究工作。
  • @AndyKorneyev 如果 op 知道 OP 想要什么,为什么他应该首先出现在这里?好的。该代码未在此处显示;我同意,OP应该发布它。但是你的意思是什么这不是在这里提出问题的好方法。到目前为止,您是否尝试过任何方法来解决您的问题? 嗯?您复制粘贴的通用模板似乎根本不适合这个问题。
  • @AndyKorneyev 我不明白为什么我的帖子不是在这里提问的好方法,你能详细说明为什么吗?我使用 Regex.Replace 尝试了很多事情,但我要么删除了所有分隔的子字符串,要么删除了第一个分隔符之后的字符串的其余部分,或者没有更改。我包括了最接近我想要的结果,这是我在这个问题上的努力。我不知道如何解决这个问题,这就是我在这个网站上寻求建议的原因。感谢您的帮助。
  • 在 SQL 中查找单引号通常表明您做错了:参数化是解决该问题的方法。

标签: c# regex string


【解决方案1】:
'(?![^']*\bdark\b)[^']*'

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

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

【讨论】:

  • 这是一个很棒的网站,但我无法让它在我的 C# 应用程序中工作。我使用了“代码生成器”功能并复制了它,但它对字符串没有任何影响。我需要阅读更多关于 Regex 的内容,以充分理解语法以翻译我认为的内容。谢谢!
  • 行得通!有点,我仍然必须包含包含整个正则表达式字符串的单引号,您在评论中省略了它。我会把它放在我的帖子里。谢谢
  • @armus47 在这种情况下最好使用逐字字符串,这样您就不必转义反斜杠:Regex.Replace(test, @"'(?![^']*\bdark\b)[^']*'", string.Empty)
【解决方案2】:

虽然 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 为替换提供回调。这样,您可以运行任意逻辑来替换字符串。

【讨论】:

  • 这很完美,是我一直在寻找的答案。我无法让 vks 的解决方案正常工作,但这是一个非常漂亮的网站。 Vignesh 的解决方案是我试图解决的不使用正则表达式的方法。但我喜欢这个解决方案,因为它使用正则表达式和附加逻辑来实现易于理解的方法。谢谢!
【解决方案3】:

这样的事情会起作用。
您可以将所有要保留的字符串添加到 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;
            }
        }

【讨论】:

  • 这是我无法让 Regex 工作时想到的方法。我对你把这些放在一起的速度印象深刻。谢谢!
【解决方案4】:

我做了这个我认为你正在考虑的尝试(使用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

【讨论】:

    【解决方案5】:

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

    @"('[^']*\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 内的字符,即可得到所需的输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-30
      • 1970-01-01
      • 2018-11-03
      • 2021-01-23
      相关资源
      最近更新 更多