String.Replace未按预期工作

时间:2017-01-28 18:48:15

标签: c# string

我有一个程序

    public void TestMethod2()
    {
        string[] keywords =
        {
            "SELECT", "FROM", "WHERE", "GROUP", "HAVING", "ORDER", "LEFT",  "RIGHT", "JOIN", "INNER", "OUTER", "ASC",
            "DESC", "AND", "OR","IN", "BETWEEN", "BY", "NOT", "ON", "AS", "CASE", "WHEN", "ELSE", "UPDATE", "SET"
        };

        var actualString = "SELECT * FROm A Join B On C in D case e join t left outer join inner join right join";

        foreach (var text in actualString.Split(' '))
        {
            var isExists = keywords.Any(x => x.Equals(text, StringComparison.OrdinalIgnoreCase));

            if (!isExists)
            {
                continue;
            }

            actualString = actualString.Replace(text, text.ToUpper());
        }


        var expectedString = "SELECT * FROM A JOIN B ON C IN D CASE e JOIN t LEFT OUTER JOIN INNER JOIN RIGHT JOIN";

    }

我是C#的新手。我不清楚为什么 Replace()方法没有按预期工作。它显示输出 SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER JOIN INNER joIN RIGHT joIN

有人可以告诉我为什么Replace()表现得像这样吗? 提前致谢。

5 个答案:

答案 0 :(得分:8)

如果您调试它,您会注意到您的关键字" in"替换第二个连接,以便您获得joIN。之后您的文本变量将尝试替换" join"用" JOIN"但它不会发现"加入"因为它的一部分是大写的。

答案 1 :(得分:2)

表现如预期。这是逐行输出:

[SELECT] -> SELECT * FROm A Join B On C in D case e join t left outer join inner join right join
[FROm]   -> SELECT * FROM A Join B On C in D case e join t left outer join inner join right join
[Join]   -> SELECT * FROM A JOIN B On C in D case e join t left outer join inner join right join
[On]     -> SELECT * FROM A JOIN B ON C in D case e join t left outer join inner join right join
[in]     -> SELECT * FROM A JOIN B ON C IN D case e joIN t left outer joIN INner joIN right joIN
[case]   -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t left outer joIN INner joIN right joIN
[join]   -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t left outer joIN INner joIN right joIN
[left]   -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT outer joIN INner joIN right joIN
[outer]  -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER joIN INner joIN right joIN
[join]   -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER joIN INner joIN right joIN
[inner]  -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER joIN INner joIN right joIN
[join]   -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER joIN INner joIN right joIN
[right]  -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER joIN INner joIN RIGHT joIN
[join]   -> SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER joIN INner joIN RIGHT joIN

您可以看到当 in IN 替换时,在第5行;然后 join joIN

替换

但是,接下来发生的事情是,您对 Keywords.Any 的调用正常工作,并匹配 join joIN ,但< em> replace 调用仍然区分大小写,并且不会进行替换。

替换是C#区分大小写,不幸的是,.NET不提供不区分大小写的版本;但是周围有解决方案。

检查this link以获取不区分大小写的替换实现。

答案 2 :(得分:0)

问题是你已经在连接中替换了IN。因此,当您要使用JOIN替换join时,比较将失败。 (加入!=加入)

答案 3 :(得分:0)

从这里的答案中得到一个清晰的想法。最后通过用 for 循环改变 foreach 来解决这个问题。谢谢你们。

public void TestMethod2()
{
    string[] keywords =
    {
        "SELECT", "FROM", "WHERE", "GROUP", "HAVING", "ORDER", "LEFT",  "RIGHT", "JOIN", "INNER", "OUTER", "ASC",
        "DESC", "AND", "OR","IN", "BETWEEN", "BY", "NOT", "ON", "AS", "CASE", "WHEN", "ELSE", "UPDATE", "SET"
    };

    var actualString = "SELECT * FROm A Join B On C in D case e join t left outer join inner join right join";

    var cnt = sqlTest.Split(' ').Count();
    for (int i = 0; i < cnt; i++)
    {
        var text = sqlTest.Split(' ')[i];
        var isExists = keywords.Any(x => x.Equals(text, StringComparison.OrdinalIgnoreCase));

        if (!isExists)
        {
            continue;
        }

        actualString = actualString.Replace(text, text.ToUpper());
    }


    var expectedString = "SELECT * FROM A JOIN B ON C IN D CASE e JOIN t LEFT OUTER JOIN INNER JOIN RIGHT JOIN";

}

答案 4 :(得分:0)

我建议使用Regex.Replace代替String.Replace

 \bKeyWord\b 

pattern 以便将子字符串视为关键字,当且仅当它是整个字时才会

 select horror 
   from torro 
  where corner = 1 
     or ordain = 2

应该变成

 SELECT horror -- even if horror has two "or"
   FROM torro  -- even if torro has two "or"
  WHERE corner = 1 -- even if corner contains "or"
     OR ordain = 2 -- even if ordain contains "or"

实现:

string[] keywords = {
  "SELECT", "FROM", "WHERE", "GROUP", "HAVING", "ORDER", "LEFT",  "RIGHT",
  "JOIN", "INNER", "OUTER", "ASC", "DESC", "AND", "OR","IN", "BETWEEN", 
  "BY", "NOT", "ON", "AS", "CASE", "WHEN", "ELSE", "UPDATE", "SET"
};

var actualString = 
  "SELECT * FROm A Join B On C in D case e join t left outer join inner join right join";

foreach (var keyword in keywords)
  actualString = Regex.Replace(
    actualString,
    @"\b" + Regex.Escape(keyword) + @"\b",
    keyword.ToUpper(),
    RegexOptions.IgnoreCase);