解析字符串 - 是否有比检查每条线更有效的方法?

时间:2012-02-11 13:37:31

标签: c# parsing

我正在开发一个解析文本文件的项目。该文件从网络设备输出。传入的字符串长度可达数千到数万行。将有可变数量的条目,其中包含以下关键字:

fcN/N is up
   Hardware is Fibre Channel, SFP is short wave laser w/o OFC (SN)
   Port WWN is 20:52:00:0d:ec:ef:b0:40
    Admin port mode is F, trunk mode is on
    snmp link state traps are enabled
    Port vsan is 10

fcipN is up
.....

port-channel-N is trunking
...... 

N是一个数字。总会有'fcN / N'条目,可能有也可能没有其他两个。 'fcip'和'port-channel'条目在每个条目之后将具有与fcN / N条目相似的状态信息。所有相同类型的条目将被分组 - 不会有fc后面跟着另一个fc的fcip。同样作为一般规则,列出所有fc条目,然后是所有端口通道然后所有fcip但我不想假设。目前我正在寻找约7种不同的RegEx模式。我通过依次检查每一行来做到这一点,但是管理所有这些是很麻烦的。我考虑过在换行符上拆分字符串然后使用某种LINQ选择来获取所有3种类型的条目,但是假设它们总是以相同的顺序分组。我还想到了3个怪物正则表达式,以匹配从一个入口到下一个入口的所有内容,但我的经验是那些难以开始工作且几乎不可读。我想到的另一件事是首先匹配三个关键字--fc或​​port-channel或fcip,然后有一个if语句匹配那些独特的模式。这仍然匹配所有3种模式的每一行。

要清楚,我有正则表达式模式。我正在寻找一种更有效的方法,而不是测试6 0 8 8场比赛的每一行。

还有其他想法吗?

3 个答案:

答案 0 :(得分:0)

我有两个想法:

(1)使用if语句首先找到正确的正则表达式的最后一种方法是非常有效。我推荐它。

(2)你可以像这样编写正则表达式:

var pattern1 = @"abc";
var pattern2 = @"def";
var unionPattern = "((" + pattern1 + ")|(" + pattern2 + "))";

这使它更具可读性。

如果您不想找到跨越线条的匹配项,则应首先将文件拆分为多行。这将提高效率,因为正则表达式具有较小的输入并且将减少回溯。

如果您的匹配跨越多行,但它们总是在换行后开始,您可以先将字符串拆分为块,如下所示:

var chunks = Regex.Split(str, "((fc\d)|(fcip\d)|(port-channel-\d)));

答案 1 :(得分:0)

使用解析器组合器库(例如Sprache)可能会获得更清晰,更简洁的代码。

不是C#程序员,我对这个库并不熟悉(也可能有其他C#),但我使用Scala解析器组合效果很好,并且它们构建并使用常规表达式解析。

是否使代码更高效可能取决于您的代码现在效率低下。

答案 2 :(得分:0)

您是在寻找原始速度还是效率?如果是前者,您可以将文件拆分为多个部分,并让一个线程同时解析每个部分。诀窍将是快速找到要拆分的边界(以便每个部分仅包含整个条目)。如果总行数很大,或者开销将超过并行化增益,您也只想要多线程。