我有一个像这样的文本文件
/*
This is a comment
I a looking to delete it
*/
//CALCULATE;
Language([Dim Currency].[Currency].&[4]) = 2057;
Language([Dim Currency].[Currency].&[2]) = 2067;
我试过这段代码
var newLines = oldLines.Select(line => new {
Line = line,
Words = line.Split("/*")
})
.Where(lineInfo => !lineInfo.Words.Contains(wordToDelete))
.Select(lineInfo => lineInfo.Line);
var newLines1 = oldLines.Select(line => new {
Line = line,
Words = line.Split("*/")
})
.Where(lineInfo => !lineInfo.Words.Contains(wordToDelete))
.Select(lineInfo => lineInfo.Line);
代码返回此
This is a comment
I a looking to delete it
//CALCULATE;
Language([Dim Currency].[Currency].&[4]) = 2057;
Language([Dim Currency].[Currency].&[2]) = 2067;
如何修改我的LINQ以使结果看起来像这样(没有块注释):
//CALCULATE;
Language([Dim Currency].[Currency].&[4]) = 2057;
Language([Dim Currency].[Currency].&[2]) = 2067;
答案 0 :(得分:2)
这是Aggregate
LINQ运算符的完美用例,因为您将字符串列表(将输入文件拆分为单独的行的结果)转换为单个字符串,输入文件没有注释块。通常,当您希望将列表缩减为单个值时,或者您希望将状态从序列的一个元素传递到下一个元素(例如,一个有用的状态)时,达到Aggregate
携带我们的是“我们是否在评论栏中?”作为布尔值。
在下面的查询中,我做了一个简化的假设,即开始和结束注释将始终在他们自己的行上。如果不是这种情况,那么Aggregate
的主体变得更复杂,但基本上是相同的(您需要添加代码来处理在“/ *”或“* /”上分割行的行为)。这是一个满足您需求的查询:
var inComment = false; // start off assuming we're not in a comment
// assume lines is some IEnumerable<string> representing the lines of your file,
// perhaps from a call to File.ReadAllLines(<file name>)
var result =
lines.Aggregate(new System.Text.StringBuilder(),
(builder, line) => {
if (!inComment)
// more code here if "/*" isn't on its own line
inComment = line.StartsWith("/*");
if (inComment)
{
// more code here if "*/" isn't on its own line
inComment &= !line.StartsWith("*/");
return builder;
}
if (!inComment) builder.AppendLine(line);
return builder;
}).ToString();
为了简化示例,我没有在Aggregate
方法中包含“我们处于评论块中”状态,而是关闭变量inComment
。通过将inComment
的类型更改为Aggregate
(而不是Tuple<Boolean StringBuilder>
,就像在上面的查询中一样)并使用StringBuilder
,可以删除Item1
以上的结算而不是inComment
和Item2
而不是builder
。
编辑:我没有解释Aggregate
方法的主体,这可能很有价值,特别是因为其他评论者使用正则表达式链接到SO问题。首先,你不能用一个正则表达式删除所有注释块,你必须使用正则表达式以及一些额外的逻辑;在linked post中,Regex.Replace
方法提供了这个额外的逻辑。这是一个比这里要求更重的解决方案。相反,您需要一个具有两种状态的简单状态机:InComment和NotInComment。当您处于InComment状态时,检查您所在的评论是否以当前行结束,如果是,则转到NotInComment状态。当您处于NotInComment状态时,检查是否在当前行开始注释。如果是这样,那么你跳过该行并移动InComment状态。如果没有,则将该行添加到输出中。 InComment状态由if (inComment)
块表示,NotInComment状态是其他所有状态。