〖编程擂台〗用C#去掉SQL语句中的注释
任务:用C#去掉SQL语句中的注释。
环境:Microsoft SQL Server 查询分析器,或 Microsoft SQL Server Management Studio Express 的查询窗口。
要求:在下面 RemoveSqlComment() 方法中写语句,使得去掉注释前后的SQL语句在“查询分析器”中执行的结果一模一样。
using System;using System.Text.RegularExpressions;class Program{ static string RemoveSqlComment(string sql) { // 在这里,发挥您有聪明才智。 } static void Main() { string sql = Console.In.ReadToEnd(); Console.WriteLine(RemoveSqlComment(sql)); }}
/// <summary>/// 字符块/// </summary>public struct BlockInfo{ /// <summary> /// 起始标记 /// </summary> public string start; /// <summary> /// 结束标记 /// </summary> public string end; /// <summary> /// 替换后追加 /// </summary> public string append; public BlockInfo(string start, string end, string append) { this.start = start; this.end = end; this.append = append; }}/// <summary>/// 过滤字符块/// </summary>/// <param name="str">目标字符串</param>/// <param name="blockInfos">字符块信息</param>/// <param name="filter">过滤留下的区块</param>/// <returns>返回被过后的字符串</returns>public string FilterBlock(string str, BlockInfo[] blockInfos, int[] filter){ if (blockInfos == null || blockInfos.Length <= 0) return str; if (filter == null || filter.Length <= 0) return str; StringBuilder result = new StringBuilder(); int block = -1; // 区块类型 从0开始,-1表示无块状态 for (int i = 0; i < str.Length; i++) { if (block == -1) // 无块状态 { string temp = string.Empty; bool changed = false; for (int j = 0; j < blockInfos.Length; j++) { if (string.Compare(str, i, blockInfos[j].start, 0, blockInfos[j].start.Length) == 0) { temp = blockInfos[j].end; block = j; if (Array.IndexOf(filter, block) >= 0) // 需要出现 result.Append(blockInfos[block].start); i += blockInfos[block].start.Length - 1; changed = true; break; } } if (!changed && Array.IndexOf(filter, block) >= 0) result.Append(str[i]); // 区块没有变化 } else // 其他状态 { if (string.Compare(str, i, blockInfos[block].end, 0, blockInfos[block].end.Length) == 0) // 状态结束 { if (Array.IndexOf(filter, block) >= 0) // 需要出现 result.Append(blockInfos[block].end); else result.Append(blockInfos[block].append); i += blockInfos[block].end.Length - 1; block = -1; } else if (Array.IndexOf(filter, block) >= 0) result.Append(str[i]); } } return result.ToString();}private void Form1_Load(object sender, EventArgs e){ string sql = @" SELECT '/* 你好 */ --' AS 注释, Field1 -- Zswang 路过 FROM TableName WHERE Date = '2008-01-01' -- /*麻烦 /*-- 奇怪 --*/"; sql = FilterBlock(sql, new BlockInfo[] { new BlockInfo("'", "'", ""), new BlockInfo("/*", "*/", ""), new BlockInfo("--", "\r\n", "\r\n")}, new int[] { -1, 0 }); Console.Write(sql);}
[解决办法]
刚才忽略了5楼,呵呵。
有这情况。。。
select/**/field1/**/from/**/table1
[解决办法]
我用堆栈。。。
select x -- abc
原始串 操作栈 数据栈
1 -- abc select x 2 abc -- select x 3 -- select x (发现操作栈栈顶是--操作符,舍弃abc)返回数据栈结果select x
[解决办法]
我的意见是不要只用一次正则!
首先确定注释的优先级
/*
--xx */ select xxxx /*
*/
这条语句能执行么?
能执行说明/**/优先级高
否则--行末优先级高
先把优先级高的注释正则掉。
然后正则优先级低的注释。
[解决办法]
不会 C#,用 Java 写了一个,我想正则表达式的语法基本上是一样的。
针对方案 7 的问题,我在替换字符串 $1 后面加了空格。
PS:实在想不出还有什么其他的情况了,呵呵。
public class Test { public static void main(String args[]){ String str = "SELECT '/* 你好 */ --' AS 注释, Field1 -- Zswang 路过\n" + "FROM TableName\n" + "WHERE Date = '2008-01-01' -- /*麻烦\n" + "/*--\n" + " 奇怪\n" + "--*/\n" + "declare @tt table(aid int primary/* 8*/ key identity/*--abd*/,aname varchar(200))--test)\n" + "insert @tt (aname) values('abcdefg')\n" + "insert @tt (aname) values('/*12345*/')\n" + "insert @tt (aname) values('abc\n" + "----\n" + "--d--efg')insert @tt (aname) values('a/*bc\n" + "----*/\n" + "--d--efg')\n" + "/*k\n" + "kks*/\n" + "/*lakjd */\n" + "select * from @tt\n" + "select/**/field1/**/from/**/table1\n" + "/* \n" + " --xx */ select xxxx /* \n" + "*/ \n"; String comment1 = "/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/"; String comment2 = "--[^\n]*+"; String quote = "'[^']*(?:''[^']*)*'"; String addition = "[^'/-]"; String regex = "(" + addition + "+|" + quote + addition + "*)|" + comment1 + "|" + comment2; System.out.println(str); System.out.println("================================================"); str = str.replaceAll(regex, "$1 "); System.out.println(str); }}
[解决办法]
未在查询分析器中测试 不知输错没有
select '/*'+ field1 +'*/' as commentField1,'-- '+ field2 +'--'+ as lineField2,/* --/* pre 'text' */ feild3,/* /* 'abc*/'*//* TEST */field4
[解决办法]