c# - 从文件中检索字符串,当多行包含完全相同的字符串时使用 Linq 进行过滤
问题描述
我正在使用 Visual Studio 和 NuGet 包 MoreLinq 作为我的以下解决方案。
我希望检索的文件的示例内容,该文件还包含其他不相关的数据:
...
#define HELLO
#include "hello.h"
code
#define BYE
#include "hello.h"
...
我对解决方案的尝试几乎完全符合我的要求。但几乎,我可以明白为什么,这是合乎逻辑的:
var files = from file in Directory.EnumerateFiles(path, ".", SearchOption.AllDirectories).Where(s => s.EndsWith(".c") || s.EndsWith(".h"))
from line in File.ReadLines(file)
.SkipWhile(l => l.TrimStart() != ("#define HELLO"))
.TakeUntil(l => l.TrimStart() == ("#define BYE"))
.ToList()
select new
{
File = file,
Line = line
};
foreach (var f in files)
{
sotredLines.Add(f.Line.Trim());
}
在这一点上,我的解决方案会给我以下结果:
#define HELLO
#include "hello.h"
code
#define BYE
如果您没有注意到,它缺少我也想检索的最后一行 -> #include "hello.h"。我解决这个问题的尝试是将以下行添加到代码中
...
.SkipWhile(l => l.TrimStart() != ("#define HELLO"))
.TakeUntil(l => l.TrimStart() == ("#define BYE"))
.TakeUntil(l => l.TrimStart() == ("#include \"hello.h\""))
...
但这(如预期)仅返回以下结果:
#define HELLO
#include "hello.h"
完全忽略了其他想要的信息。因为#include "hello.h"出现多次,并且它在找到的第一个处停止。
我只想从提到的文件中检索这些行,而不会丢失其中一行:
#define HELLO
#include "hello.h"
code
#define BYE
#include "hello.h"
对于仍在使用 Linq 的解决方案,请参阅下面的@Freggar 答案。
解决方案
您可以在其中设置一个标志TakeUntil
,表明您已经过去#define BYE
:
bool byeFlag = false;
var p = from line in File.ReadLines(file)
.SkipWhile(l => l.TrimStart() != ("#define HELLO"))
.TakeUntil(l =>
{
bool ret = byeFlag;
if (l.TrimStart() == "#define BYE")
{
byeFlag = true;
}
return ret;
})
.ToList()
select new
{
File = file,
Line = line
};
但正如已经提到的,也许 LINQ 并不是你想要做的最好的工具。也许像ANTLR这样的解析器更适合这项工作?
推荐阅读
- etl - 如何在 Datastage 中将 2 位数年份更改为 4 位数年份?
- sql - 任何人都可以检查查询我也想提取年份和月份列
- sql - 如何使用触发器将插入的值与现有值进行比较和更新?
- python-3.x - 填充系列 1m 频率跳过周末
- php - 具有不同属性的jQuery切换并应用ajax
- java - AirMap 找不到导入
- c++ - 如何在 R 加载表中注册 C 符号?
- c# - 操作 System.Drawing.Image 并使用相同的 ImageFormat 保存
- php - 如果从 php 中的数据库中获取数据,则查看数据使用情况
- javascript - 向下滚动时无限滚动不起作用