C# 使用c中的正则表达式跳过文本文件中带破折号的行#
我有一个包含SQL命令的文本文件,我已经编写了一些代码来“忽略”注释和空格,以便只获得命令(我将在下面发布代码和文本文件和输出的示例),这很好,但在该文本文件中,我还需要忽略“------------------------------------”这样的行,我已经编写了忽略它的代码,但是我不明白为什么它不能正常工作。 代码: 这是。我在其中添加了“忽略”虚线: .Where(line=>!Regex.IsMatch(line,@“^[\s-]+$”)C# 使用c中的正则表达式跳过文本文件中带破折号的行#,c#,parsing,text,text-files,C#,Parsing,Text,Text Files,我有一个包含SQL命令的文本文件,我已经编写了一些代码来“忽略”注释和空格,以便只获得命令(我将在下面发布代码和文本文件和输出的示例),这很好,但在该文本文件中,我还需要忽略“------------------------------------”这样的行,我已经编写了忽略它的代码,但是我不明白为什么它不能正常工作。 代码: 这是。我在其中添加了“忽略”虚线: .Where(line=>!Regex.IsMatch(line,@“^[\s-]+$”) 带破折号的文本示例: / ------
带破折号的文本示例:
/
---------------------------------------------------------------------
UPDATE CDPREPORTSQL
SET COMANDOSQL_FROM =
'SELECT DESCONTO,EMPCOD,EMPDSC,LINVER,NOMESISTEMA,OBS,ORCCOD,ORCVER,PEDCOD,PEDDSC,
ROUND(PRCUNIT*#CAMBIO#,5) PRCUNIT,
ROUND(PRCUNITSEMDESC*#CAMBIO#,5) PRCUNITSEMDESC,
PROPCHECK,QTDGLOB,QTDPROP,REFCOD,REFDSC,EMPCODVER, COEFGERAL_PLT FROM #OWNER#.VW_PROPOSTAS',
COMANDOSQL_WHERE =
'WHERE ORCCOD=#ORCCOD# AND ORCVER=#ORCVER# AND NOMESISTEMA=#NOMESISTEMA# AND PEDCOD=#MYCOD#'
WHERE REPID = 'CDP0000057'
/
---------------------------------------------------------------------
输出示例:
---------------------------------------------------------------------
UPDATE CDPREPORTSQL
SET COMANDOSQL_FROM =
'SELECT DESCONTO,EMPCOD,EMPDSC,LINVER,NOMESISTEMA,OBS,ORCCOD,ORCVER,PEDCOD,PEDDSC,
ROUND(PRCUNIT*#CAMBIO#,5) PRCUNIT,
ROUND(PRCUNITSEMDESC*#CAMBIO#,5) PRCUNITSEMDESC,
PROPCHECK,QTDGLOB,QTDPROP,REFCOD,REFDSC,EMPCODVER, COEFGERAL_PLT FROM #OWNER#.VW_PROPOSTAS',
COMANDOSQL_WHERE =
'WHERE ORCCOD=#ORCCOD# AND ORCVER=#ORCVER# AND NOMESISTEMA=#NOMESISTEMA# AND PEDCOD=#MYCOD#'
WHERE REPID = 'CDP0000057'
---------------------------------------------------------------------
Update Orc set MercadoInt = 'N'
Where MercadoInt is NULL
以下是我需要处理的可能出现的语句示例:
/* */
UPDATE Orc
/*UPDATE comando */
set MercadoInt = 'N', Coef_KrMo = 1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL
/
另一个:
/* */
---- comment
UPDATE Orc set MercadoInt = 'N', Coef_KrMo =
-1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL
/
/* */
UPDATE Orc set MercadoInt = 'N', Coef_KrMo = 1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL
/
还有一个:
/* */
---- comment
UPDATE Orc set MercadoInt = 'N', Coef_KrMo =
-1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL
/
/* */
UPDATE Orc set MercadoInt = 'N', Coef_KrMo = 1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL
/
注意,即使语句中有注释部分,也需要处理它们。 请注意,其他一切都正常工作(它“忽略”注释) (和空格)
“/”仅用于分割文本文件中的命令据我所知,您有一个包含多个SQL命令的文本文件,由以下命令分隔:
/
---------------------------------------------------------------------
您只希望文本位于这些破折号之间。如果是这样,为什么不拆分文本,然后取出所有元素
正则表达式似乎有效:
\/\n\n-+
根据Regex.Split文档,代码为:
string input = File.ReadAllText(caminho);
string pattern = "\/\n\n-+";
string[] substrings = Regex.Split(input, pattern);
foreach (string match in substrings)
{
//do cool stuff with your cool query
}
如果您不想使用正则表达式,也可以使用
!line.TrimStart().StartWith(“-”)
应该是相同的,而且我认为它更快。我已经完成了这样的代码,到目前为止运行良好
public string[] Parser(string caminho)
{
List<string> Commands2 = new List<string>();
string text = File.ReadAllText(caminho);
var Linha = Regex.Replace(text, @"\/\**?\*\/", " ");
var Commands = Linha.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
.Where(line => !string.IsNullOrWhiteSpace(line))
.Where(line => !Regex.IsMatch(line, @"^[\s\-]+$"))
.ToArray();
Commands2 = Commands.ToList();
for(int idx = 0; idx < Commands2.Count; idx ++)
{
if (Commands2[idx].TrimStart().StartsWith("-"))
{
string linha = Commands2[idx];
string linha2 = linha.Remove(linha.IndexOf('-'), linha.LastIndexOf('-') - 1);
Commands2[idx] = linha2;
}
}
//test the output to a .txt file
StreamWriter Comandos = new StreamWriter(Directory.GetParent(caminho).ToString() + "Out.txt", false);
foreach (string linha in Commands2)
{
Comandos.Write(linha);
}
Comandos.Close();
return Commands2.ToArray();
}
publicstring[]解析器(stringcaminho)
{
List Commands2=新列表();
string text=File.ReadAllText(caminho);
var Linha=Regex.Replace(文本,@“\/\**?\*\/”,“”);
var Commands=Linha.Split(新[]{'/'},StringSplitOptions.RemoveEmptyEntries)
.Where(line=>!string.IsNullOrWhiteSpace(line))
.Where(line=>!Regex.IsMatch(line,@“^[\s\-]+$”)
.ToArray();
Commands2=Commands.ToList();
for(intidx=0;idx
在他们分析了我的代码之后,他们说我不能使用这个(如图所示)
因为它不适用于某些情况,例如
陈述的中间部分。
我现在将尝试使用Tsql120Parser执行此操作
下面的代码适用于您给出的示例
private const string DashComment = @"(^|\s+)--.*(\n|$)";
private const string SlashStarComment = @"\/\*.*?\*\/";
private string[] CommandSplitter(string text)
{
// strip /* ... */ comments
var strip1 = Regex.Replace(text, SlashStarComment, " ", RegexOptions.Multiline);
var strip2 = Regex.Replace(strip1, DashComment, "\n", RegexOptions.Multiline);
// split into individual commands separated by '/'
var commands = strip2.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
return commands.Where(line => !String.IsNullOrWhiteSpace(line))
.ToArray();
}
我把你在问题中贴出的三个例子放在一个字符串中。它看起来像这样(是的,很难看):
然后,我调用了CommandSplitter
:
var result = CommandSplitter(Test1);
并输出结果:
foreach (var t in result)
{
Console.WriteLine(t);
Console.WriteLine("////////////////////////");
}
删除了/**/代码>注释和--…
注释
它也适用于这个例子:
private const string Test2 =
"Update Orc set /* this is a comment */ MercadoInt = 'N' -- this is another comment\n" +
"Where MercadoInt is NULL --another comment";
输出:
---------------------------------------------------------------------
UPDATE CDPREPORTSQL
SET COMANDOSQL_FROM =
'SELECT DESCONTO,EMPCOD,EMPDSC,LINVER,NOMESISTEMA,OBS,ORCCOD,ORCVER,PEDCOD,PEDDSC,
ROUND(PRCUNIT*#CAMBIO#,5) PRCUNIT,
ROUND(PRCUNITSEMDESC*#CAMBIO#,5) PRCUNITSEMDESC,
PROPCHECK,QTDGLOB,QTDPROP,REFCOD,REFDSC,EMPCODVER, COEFGERAL_PLT FROM #OWNER#.VW_PROPOSTAS',
COMANDOSQL_WHERE =
'WHERE ORCCOD=#ORCCOD# AND ORCVER=#ORCVER# AND NOMESISTEMA=#NOMESISTEMA# AND PEDCOD=#MYCOD#'
WHERE REPID = 'CDP0000057'
---------------------------------------------------------------------
Update Orc set MercadoInt = 'N'
Where MercadoInt is NULL
更新
上面的代码返回一个命令数组。每个命令由多行组成。如果要删除行开头的多余空格并消除空行,则必须单独处理每个命令。因此,您希望像这样扩展命令拆分器
:
private string[] CommandSplitter(string text)
{
// strip /* ... */ comments
var strip1 = Regex.Replace(text, SlashStarComment, " ", RegexOptions.Multiline);
var strip2 = Regex.Replace(strip1, DashComment, "\n", RegexOptions.Multiline);
// split into individual commands separated by '/'
var commands = strip2.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
return commands.Select(cmd => cmd.Split(new[] {'\n'})
.Select(l => l.Trim()))
.Select(lines => string.Join("\n", lines.Where(l => !string.IsNullOrWhiteSpace(l))))
.ToArray();
}
所有这些似乎都相当复杂和缓慢。如果您只想查找/拒绝破折号行,为什么不使用:
if (line.StartsWith("----"))
(假设4个破折号足以毫不含糊地检测此类线条)
如果行的开头可能有空格,则:
if (line.Trim().StartsWith("----"))
这种方法不仅比正则表达式可读性大得多,而且速度也可能快得多。如果您需要以与SQL相同的方式进行注释,那么这种方法很容易变得比正则表达式通常能够处理的更复杂。例如,如果一个包含破折号的行恰好作为多行字符串文字的一部分出现,那么它可能是一个完全有效的输入。那么你是说这种方法在某些情况下是无效的?不使用第三方软件或附加组件的最佳解决方案是什么?另外,据我所知,命令与this@Damien_The_Unbeliever如果你需要,我可以发布一个全文文件的链接,让你看一看。几乎是xD,我有用“/”分隔的命令,虚线只是无缘无故地存在。编译这些文件的不是我,我不能改变,我需要照原样对待它们。总之,命令被“/”分开,破折号是需要忽略的红色。你的意思是“/”是始终存在的分隔符,但是-”的行并不总是存在?也有这样的输入/sqlquery/sqlquery
是的,“/”是分隔符,-----的行并不总是在那里。在这里,我给你一个全文文件的链接:根据你的文档,我同意Damien的观点,正则表达式在你的情况下并不理想。对我来说,有太多不同的文本,使一个有效的正则表达式。另外,破折号和反斜杠在文本中的位置看起来非常随机,因此可能适用于此特定文件的正则表达式可能无法适用于下一个文件。你是对的,但如果我不能使用VS及其默认工具之外的任何东西,我不知道如何处理该文件。如果我们假设所有的文件都是这样的?一些虚线和注释,但没有任何东西会干扰此方法的责任?没有专用的sql解析器