基于输入的正则表达式创建


Regex creation based upon input

我有一个用PHP编写的Web应用程序,它结合了Javascript和JQuery,将用作我公司的库存管理系统(IMS)。我希望能够创建的是基于用户输入的值的正则表达式。

这背后的想法是,大多数制造商的序列号模式、字符长度以及字母到数值的混合对于某个部分都是唯一的。因此,当将零件添加到IMS并将第一个序列号扫描到系统中时,我希望构建一个正则表达式语句并将其保存到与该零件类型对应的数据库表中。将来扫描序列号时,应自动选择该部件作为部件类型,因为它与该制造商的序列号架构匹配。我知道这种方法可能并不总是适用于单个部分,因此我甚至可以返回与架构匹配的部件列表,而不是用户需要在目录中查找它。

我问题的基础是,让代码中的函数能够破译用户给出的值以创建正则表达式的最佳起点是什么?我不是在要求一个完整的功能,而是一个如何看待我的情况和目标的起点,以便我能够理解从哪里开始。我已经挠了足够长的时间,并多次开始编写函数,只是为了删除整个块,知道我正在走向灾难。

代码中的任何内容都是可能的 - 这可行吗?


编辑 - 添加的示例值

DVD-RW (光驱)

  • 1613518L121
  • 1613509L121
  • 1613519L121

VGA 输出卡

  • 0324311071068
  • 0324311071134

COM 扩展卡

  • 608131234
  • 608131237

硬盘

  • WMAYUJ753738
  • WMAYUJ072099
  • WMAYUJ683739
  • WMAYUJ844900

如您所见,某些值将仅是特定长度字符的数字。其他人的开头会有字母字符,后跟一系列数字。其他人可能具有相互穿插的字母/数字字符。在大多数情况下,字母/数字规则的简单长度都适合在我们的商品列表中识别单一零件类型。但是,在多个表达式与值匹配的情况下,我可以简单地让应用程序显示与正则表达式匹配的两个或多个产品的列表,并提示用户选择正确的部分。总体而言,这将节省在 WMS 数据库中选择产品类型的时间和错误。

感谢您的评论。我知道我不是在问一个只有一个答案的问题。我正在寻找一个关于如何最好地逐步执行字符串并吐出与值匹配的相应 Regex 语句的起点。

正如@Pete所说,我认为你给自己设定了一个过于雄心勃勃的目标。 一些想法,也许从您的特定需求中过于概括。

我认为您要扫描像 1-56592-487-8 这样的序列号并推断正则表达式/''d-''d{5}-''d{3}-''d/匹配给定制造商的此类部件。 (这恰好是我的"Java in a Nutshell"副本的ISBN-10。 ISBN 不是序列号,但与我一起工作。 但是您无法从少数示例中推断制造商使用哪种模式。 也许第一个字符位置是十六进制数字 (0-F)。 也许最后一个字符是一个校验和,可以是数字或 X(如 ISBN)。 也许有一个后缀,并不总是存在,表示植物。 因此,您会发现自己在零件的新实例出现时为同一制造商/零件类型构建了许多模式。

你也会遇到相反的问题。 小部件制造商使用正则表达式/[A-Z]{3}''d{7}/,声波螺丝刀制造商使用相同的模式。

也就是说,你能做的最好的事情是这样的:

for each character in the scanned serial number
    if it is a capital letter
        add [A-Z] to the regular expression
    else if it is a digit
        add 'd to the regular expression
    else 
        add the character itself to the regular expression, escaped as necessary
 end for
 collapse multiple occurrences with the {,} interval qualifier

车辆识别号码的规则也可能鼓舞人心。 考虑一下如何推断VIN的规则,举几个例子。

编辑:对不起,我的示例代码有问题,您需要这种算法作为您将猜测的部分的第一步:最长子字符串或这个

您将需要添加迭代和一些掩码,如上面和大卫解释的那样,在下面的示例中,没有猜测 DVD-RW 的"L121"(正如我所说,我必须从"常见"开始)。因此,您需要找到所有常见的连续子序列,并确定哪个是相关的!(可能带有一种最大化增益函数)

使用第二个链接long_substr:

>>> for x in d:
    for y in d:
        if x == y: continue
        common = long_substr([x, y])
        length = len(common)
        if x.startswith(common) and y.startswith(common):
            print "'t".join((x, y, str(length), common))

产生=>

0324311071068   0324311071134   10  0324311071
0324311071134   0324311071068   10  0324311071
1613519L121 1613518L121 6   161351
1613519L121 1613509L121 5   16135
WMAYUJ844900    WMAYUJ753738    6   WMAYUJ
WMAYUJ844900    WMAYUJ072099    6   WMAYUJ
WMAYUJ844900    WMAYUJ683739    6   WMAYUJ
WMAYUJ753738    WMAYUJ844900    6   WMAYUJ
WMAYUJ753738    WMAYUJ072099    6   WMAYUJ
WMAYUJ753738    WMAYUJ683739    6   WMAYUJ
1613518L121 1613519L121 6   161351
1613518L121 1613509L121 5   16135
WMAYUJ072099    WMAYUJ844900    6   WMAYUJ
WMAYUJ072099    WMAYUJ753738    6   WMAYUJ
WMAYUJ072099    WMAYUJ683739    6   WMAYUJ
WMAYUJ683739    WMAYUJ844900    6   WMAYUJ
WMAYUJ683739    WMAYUJ753738    6   WMAYUJ
WMAYUJ683739    WMAYUJ072099    6   WMAYUJ
608131237   608131234   8   60813123
1613509L121 1613519L121 5   16135
1613509L121 1613518L121 5   16135
608131234   608131237   8   60813123

---第一个越野车回复从这里开始

以下是我回复的第一部分,这只能帮助您了解我错在哪里,并可能给您一些想法:

使用最长公共子序列问题求解器 LCS 的样本满足您的特定需求,我可以认为这是猜测什么是共同点的过程的第一步?

它是在 Python 中,但对于演示部分,它可以轻松阅读(或者可以在 IDLE(python 编辑器)中剪切和粘贴),前提是您使用上面第一个链接的 ActiveState 代码配方

这与生物信息学有关(想想基因比对)

您将需要一些东西来决定什么是最有趣的常见序列(可能具有最小的长度?然后继续像大卫已经提出或在我的评论中提出的那样进行屏蔽

(起初我没有看到LCS什么不是LCS连续求解器,而您将需要它!所以我第一次使用 LCS 求解器是错误的:(因为它不是连续的,所以我有 MAYUJ8 或 WMAYUJ7 而不是 WMAYUJ - 更短!而求解器找到最长的常用字符,而不期望它们是连续的!- 再次对此感到抱歉)

>>> raw = """1613518L121
1613509L121
1613519L121
0324311071068
0324311071134
608131234
608131237
WMAYUJ753738
WMAYUJ072099
WMAYUJ683739
WMAYUJ844900"""
>>> d = dict()
>>> for line in raw.split("'n"):
    if not line.strip(): continue
    value = line.strip()
    d[value] = 1
>>> for x in d:
    for y in d:
        if x == y: continue
        length = LCSLength(x, y)
        common = LCS(x,y)
        if  length >= 3 and x.startswith(common):
            print "'t".join((x, y, str(length), common))

产生=>

0324311071068   0324311071134   10  0324311071
0324311071068   608131234   4   0324
0324311071134   0324311071068   10  0324311071
WMAYUJ844900    WMAYUJ753738    7   WMAYUJ8
WMAYUJ753738    WMAYUJ072099    7   WMAYUJ7
608131237   608131234   8   60813123
608131234   608131237   8   60813123

运行垃圾邮件检测算法(统计算法,如贝叶斯或类似的"学习"算法)。这会或不会帮助你,但如果不是,老实说,我怀疑你永远不会在这里制作任何有用的逻辑算法。