需要正则表达式来匹配用户生成的模式

时间:2012-01-12 23:17:58

标签: c# asp.net regex pattern-matching

我有一个用C#(3.5框架)编写的ASP.NET应用程序,用户为我提供了一个我们已经制定规则的模式列表。我可以编写代码来手动计算每个模式,但更愿意找到一种方法来使用正则表达式(或任何方法)来处理它们,这样我就可以让用户创建更多模式(当然遵循一些指导原则)将来

我会尽力展示我想要做的事情。我非常感谢你的帮助。

以下是一些模式:

模式1: 要素1:CxxxxRxxxx 元素2:CxxxxRzzzz 结果:Bucket 1

模式2: 要素1:CxxxxRxxxx
要素2:CxxxxRxxxx 结果:铲斗2

模式3: 要素1:PCxxxxxxxx
元素2:PCzzzzzzzz 结果:Bucket 3

模式4: 要素1:PCxxxxxxxx
要素2:UxxxxRxxxx 结果:Bucket 4

这是他们的意思以及我需要如何处理它们。首先,所有元素的长度始终为10个字符。每个模式的字母字符都是常量。 X和Z可以是数字或字母。 X和Z在模式中的含义是2个元素的其他部分是否相互匹配。

例如,我的输入数据是“C1234R5678”作为元素1,“C1234R9999”作为元素2.在这种情况下,结果将是“Bucket 1”,因为这匹配为此条件定义的模式(后面的数字) “C”匹配,但“R”之后的数字不匹配。

在另一个例子中,我的输入数据是“C1234R5678”作为元素1,“C1234R5678”作为元素2.在这种情况下,结果将是“Bucket 2”,因为这匹配为此条件定义的模式(后面的数字) “C”匹配,“R”匹配后的数字也是如此。

在另一个例子中,我的输入数据是“PC12345678”作为元素1,“PC87654321”作为元素2.在这种情况下,结果将是“Bucket 3”,因为这匹配为此条件定义的模式(后面的数字) “PC”不匹配。)

在最后一个例子中,我的输入数据是“PC12345678”作为元素1,“U1234R5678”作为元素2.在这种情况下,结果将是“Bucket 4”,因为这匹配为此条件定义的模式(4 “PC”后的数字与U后的4个数字匹配,PC元素的后4位数字与元素2的R后的4位数相匹配。

正如您所看到的,模式可能会有所不同,因为有时候您会在一封信之后识别一个字母或整个数字后面的4个数字。

感谢您的时间。

2 个答案:

答案 0 :(得分:1)

一种方法是连接元素(可能使用不能出现在元素中的分隔符),因此每个元素都可以由单个正则表达式匹配。使用capturing and backreferences强制以后的子字符串匹配。使用否定lookaheads确保子字符串与之前的子字符串不匹配;否则,您必须依赖于检查模式的顺序以确保模式匹配正确(在示例中,您必须在存储桶1之前检查存储桶2)。使用squiggly bracket quantifiers匹配特定数量的字符。

/C(.{4})R\1-C\1R(?!\1).{4}/ -> bucket 1
/C(.{4})R\1-C\1R\1/         -> bucket 2
/PC(.{8})-PC(?!\1).{8}/     -> bucket 3
/PC(.{4})(.{4})-U\1R\2/     -> bucket 4

您可以将零件限制为仅包含字母数字字符([A-Za-z\d])或标识符字符(\w,而不是“任意”字符(点),相当于'[A-Za-z \ d _]')。

将映射存储在列表中,然后在确定要使用的存储区时迭代列表。模式和存储桶之间的其他映射可以附加到列表中。

当然,这需要您的用户能够编写正则表达式,尽管您可以提出一种更简单的语言转换为正则表达式。例如,您可以让用户仅指定“{n}”和“\ k”,其中前者表示匹配许多不应与任何先前组匹配的字符,后者表示匹配k th “{n}”。要翻译为正则表达式,请将每个“{n}”替换为“(。{n})”(或“(\ w {n})”),前缀为“(?!\ k)”,表示k = 1到n -1。使用sort-of-C#,替换可以指定为:

(1..n-1).sum(k => "(?!\\" + k + ")") + "(\\w{"+n+"})"

答案 1 :(得分:0)

您可以执行以下操作:

For each (Element1,Element2) pair:
    match Element1,Element2 on "(x+|z+)" -> matches1,matches2

    for (i=0;i<min(matches1,matches2);i++) {
        replace 'x+' by '([A-Za-z0-9]{matches1[i].Length})'
        // note: need the brackets here to act as capturing brackets
        // so that backreferences can be used!

        if matches2[i] is 'xxxxx':
            replace 'x+' by '(?!\i)[A-Za-z0--9]{matches2[i].Length}'
        else if matches2[i] is 'zzzzz':
            replace 'z+' by '\i'
    }
    Then replace miscellaneous leftover 'xxxx' by '[A-Za-z0-9]{lengthofmatch}'.

    Then join the new Element1 and Element2 by a delimiter e.g. '-'

这将构造一堆字符串,如:

//Pattern 1
C([A-Za-z0-9]{4})R([A-Za-z0-9]{4})-C(?!\1)[A-Za-z0-9]{4}R\2
//Pattern 2
C([A-Za-z0-9]{4})R([A-Za-z0-9]{4})-C(?!\1)[A-Za-z0-9]{4}R(?!\2)[A-Za-z0-9]{4}
//Pattern 3
PC([A-Za-z0-9]{8})-PC\1
//Pattern 4
PC([A-Za-z0-9]{8})-U(?!\1)[A-Za-z0-9]{4}R[A-Za-z0-9]{4}

然后,对于每个输入数据,添加由' - '分隔的Element1和Element2(例如"C1234R5678-C1234R9999")并匹配每个模式,并在第一个匹配时停止。