2017-07-25 71 views
3

我想在C#中创建一个函数(W /一套辅助功能,如果需要),将执行类似的事情awk '/start/,/end/' file - 除了它会包括所有最后的比赛,而不是终止在第一场比赛。搜索字符串或StringBuilder与模式范围/开始/ /结束/

比方说,我们有:

# 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类型?

我也希望这是高性能的,听到建议如何使它成为可能会令人敬畏。一般指导和实施细节表示赞赏。

+2

具体怎么是你的问题?这应该只适用于这种特殊情况,还是应该与awk在同一范围内工作? – MetaColon

+2

'StringBuilder'用于_building_字符串。首先构建它,然后生成整个字符串并使用'String'函数进行搜索。 –

+0

@MetaColon - 比一般的特例更具普遍性。我将其指定为:“给定一个utf8字符串中存在的两个模式,找到以第一个模式开始并以第二个模式结束的文本。”可以添加包含/ end/pattern的整行的额外要求。 @D赤柱 - 得到确认你是在正确的轨道上总是很好,谢谢。 –

回答

0

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

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

为了达到我所追求的逻辑,有三种状态:在找到开始之前,在找到结尾之前,我们仍然找到结尾。我选择通过使用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 [email protected]" 
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); 
    } 
} 
相关问题