解析字符串-有没有比检查每一行更有效的方法

本文关键字:一行 有效 方法 字符串 有没有 检查 | 更新日期: 2023-09-27 18:24:02

我正在做一个解析文本文件的项目。该文件是从网络设备输出的。传入字符串的长度从几千行到数万行不等。将有一个可变数量的条目的关键字如下:

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"answers"port channel"条目在每个条目之后都将具有与fcN/N条目类似的状态信息。所有相同类型的条目都将被分组——不会有一个fc后接一个fcip后接另一个fc。同样作为一般规则,列出了所有fc条目,然后列出了所有端口通道,然后列出所有fcip,但我不想这么认为。目前,我正在寻找大约7种不同的RegEx模式。我通过依次检查每一行来做到这一点,然而管理所有这些都很麻烦。我想过在换行符上拆分字符串,然后进行某种LINQ选择,以获得这3种类型的条目中的所有条目,但前提是它们总是按相同的顺序分组。我还考虑了3个怪物正则表达式来匹配从一个条目到下一个条目的所有内容,但我的经验是,这些正则表达式很难工作,而且几乎无法读取。我想到的另一件事是首先匹配三个关键字-fc或port channel或fcip,然后有一个if语句来匹配这些关键字特有的模式。不过,这仍然与所有3种模式的每条线相匹配。

需要明确的是,我有Regex模式在工作。我正在寻找一种更有效的方法来做到这一点,而不是测试每一行6 0 r 8匹配。

还有其他想法吗?

解析字符串-有没有比检查每一行更有效的方法

我有两个想法:

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

(2) 您可以这样编写regex:

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

这使它可读性更强。

如果您永远不想找到一个跨行的匹配项,则应首先将文件拆分为多行。这将提高效率,因为正则表达式的输入更小,回溯更少。

如果你的匹配跨越多行,但它们总是在新行之后开始,你可以先把字符串分成块,如下所示:

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

使用解析器组合子库(如Sprache)可以获得更清晰、更简洁的代码。

作为一名C#程序员,我对这个库并不熟悉(很可能还有其他C#库),但我使用了Scala语法分析器组合子,效果很好,它们建立在正则表达式解析的基础上并使用正则表达式解析。

它是否能让你的代码更有效率可能取决于你现在的代码效率有多低。

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