简体   繁体   English

String.Replace未按预期工作

[英]String.Replace is not working as expected

I have a program 我有一个程序

    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";

    }

I am a newbie in C#. 我是C#的新手。 I am not clear why the Replace() method is not working as expected. 我不清楚为什么Replace()方法没有按预期工作。 It is showing the output SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER joIN INner joIN RIGHT joIN 它显示输出SELECT * FROM A JOIN B ON C IN D CASE e joIN t LEFT OUTER JOIN INNER joIN RIGHT joIN

Can someone please enlighten me why Replace() is behaving like this? 有人可以告诉我为什么Replace()表现得像这样吗? Thanks in advance. 提前致谢。

If you debug it you will notice that your keyword "in" replaces second join so you get joIN. 如果你调试它,你会注意到你的关键字“in”取代了第二个连接,所以你得到了joIN。 Later your text variable will try to replace "join" with "JOIN" but it won't find "join" because part of it was uppercased. 稍后您的文本变量将尝试将“join”替换为“JOIN”,但它不会找到“join”,因为它的一部分是大写的。

It is behaving as expected. 它表现得像预期的那样。 Here is the output line by line: 这是逐行输出:

[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

You can see that when in gets replaced by IN , at line 5; 你可以看到, 得到由IN所取代,在5号线; then join gets replaced by joIN 然后joinjoIN取代

But then, what happen is that your call to Keywords.Any works properly, and matches join and joIN , however, the replace call is still case sensitive and the replace will not take place. 但是,接下来发生的事情是您对Keywords.Any的调用正常工作,并匹配joinjoIN ,但是, 替换调用仍然区分大小写,并且不会发生替换。

Replace is C# is case sensitive and, unfortunately, .NET doesn't offer a case insensitive version; 替换是C#区分大小写,不幸的是,.NET不提供不区分大小写的版本; but there are solutions floating around. 但是周围有解决方案。

Check this link for an implementation of a case insensitive replace. 检查此链接以获取不区分大小写的替换的实现。

The problem is that you already replace the IN in join. 问题是您已经在连接中替换了IN。 Therefore the comparison fails when you want to replace join with JOIN. 因此,当您要使用JOIN替换join时,比较将失败。 (joIN != join) (加入!=加入)

Got a clear idea from the answers here.Finally solve that by changing the foreach with for loop. 从这里的答案中得到一个清晰的想法。最后用for循环改变foreach 解决这个问题。 Thank you all. 谢谢你们。

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";

}

I suggest using Regex.Replace instead of just String.Replace with 我建议使用Regex.Replace而不仅仅是String.Replace

 \bKeyWord\b 

pattern in order treating a substring as a keyword if and only if it is a whole word : 模式 ,以便将子字符串视为关键字,当且仅当它是一个完整的单词时

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

should be turned into 应该变成

 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"

Implementation: 执行:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM