gpt4 book ai didi

c# - 使用模式 range/start//end/搜索 String 或 StringBuilder

转载 作者:行者123 更新时间:2023-11-30 18:16:59 25 4
gpt4 key购买 nike

我想在 C# 中创建一个函数(如果需要,带有一组辅助函数),它会执行与 awk '/start/,/end/' file 类似的事情 - 除了它将包括所有最后的匹配项,而不是在第一个匹配项上终止。

假设我们有:

# cat text
"13:08:30:5276604 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:5736962 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:6227343 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:6757752 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:7208103 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:7668739 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:8129079 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"

预期:

"13:08:30:6227343 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:6757752 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:7208103 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:7668739 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"

AWK 输出:

# awk '/13:08:30:62/,/13:08:30:7/' text
"13:08:30:6227343 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:6757752 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"
"13:08:30:7208103 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M"

我最初认为我可能只是通过两个条件得到正则表达式匹配 pattern_1 | pattern_2 但是,如果匹配值之间存在值,这将不起作用。

我还发现 C# StringBuilder 类没有 .indexOf().lastIndexOf() 方法(我在 JAVA 方面有更多经验,所以想使用这些直到我看到 C# 没有它们)。由于我没有这些方法并且可能需要实现它们,所以我想问一下这是否是可行的方法?如果需要大量搜索,本节甚至建议使用 String:MSDN - 我当然也可以使用它。我选择使用 StringBuilder 因为字符串连接是不断执行的,我应该在构建字符串时使用 stringbuilder 类型(很多连接),然后转换为 string 类型搜索?

我也希望它具有高性能,如果能听到有关如何实现它的建议,那就太棒了。一般指导和实现细节表示赞赏。

最佳答案

如果您需要处理一个潜在的大文件,您最好使用 StreamReader并使用 ReadLine 每行处理它方法。这可以防止您最终在内存中得到完整的文件,就像您在使用 StringBuilder 时可能会遇到的那样。通过使用摘要 TextReader在实现上,您可以将字符串用作(文件)流。

要检查开始和结束是否匹配,您可以使用 Regex class .这是Match方法返回一个具有 Success 属性的实例,当找到匹配项时该属性将为真。

为了实现你所追求的逻辑,我估计有三种状态:在我们找到开始之前,在我们找到结束之前,同时我们仍然找到结束。我选择通过使用 yield 在迭代器中实现它关键字,因为它几乎可以免费给我状态机。

实现如下:

void Main()
{
// use a streamreader to read characters
// the .ctor accpets an Encoding as second parameter
using(var sr = new StreamReader(@"sample.txt"))
{
ReadFromBeginToEnd("13:08:30:62","13:08:30:7",sr);
}

var text =@"
13:08:30:6227343 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M
13:08:30:6757752 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M
13:08:30:7208103 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M
13:08:30:7668739 Main: 41044 - 48.7617 M-- Other PIDS 2 - 79.1016 M";
using(var sr = new StringReader(text))
{
ReadFromBeginToEnd("13:08:30:62","13:08:30:7", sr);
}
}

// enumerate over the lines from the streamreader
// accepting two regexes, start and end
IEnumerable<string> FromBeginToEnd(TextReader rdr, Regex start, Regex end)
{
// 1st state
var line = rdr.ReadLine(); // initial read, null means we're done
// read the lines until we hit our start match
while(line != null && !start.Match(line).Success)
{
// don't return these lines
line = rdr.ReadLine();
}
// 2nd state
// read the lines while we didn't hit our end match
while(line != null && !end.Match(line).Success)
{
// return this line to the caller
yield return line;
line = rdr.ReadLine();
}
// 3rd state
// read the lines while we find our end match
while(line != null && end.Match(line).Success)
{
// return this line to the caller
yield return line;
line = rdr.ReadLine();
}
// iterator is done
yield break;
}

// take a start and end string that can be compiled to a regex
// and a file (fullpath)
void ReadFromBeginToEnd(string start, string end, TextReader reader)
{
// loop over the lines that mach the criteria
// FromBeginToEnd is our custom enumerator
foreach(var line in FromBeginToEnd(reader, new Regex(start), new Regex(end)))
{
// write to standard out
// but this can be an StreamWriter.WriteLine as well.
Console.WriteLine(line);
}
}

关于c# - 使用模式 range/start//end/搜索 String 或 StringBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45302141/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com