2

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

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

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

代码中的任何东西都是可能的——这可行吗?


编辑 - 添加样本值

DVD-RW(光驱)

  • 1613518L121
  • 1613509L121
  • 1613519L121

VGA 输出卡

  • 0324311071068
  • 0324311071134

COM 扩展卡

  • 608131234
  • 608131237

硬盘驱动器

  • WMAYUJ753738
  • WMAYUJ072099
  • WMAYUJ683739
  • WMAYUJ844900

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

感谢您的评论。我知道我问的问题不是只有一个答案。我正在寻找一个关于如何最好地遍历字符串并吐出与该值匹配的相应正则表达式语句的起点。

4

3 回答 3

2

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

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

你也会遇到相反的问题。小部件制造商使用正则表达式 /[AZ]{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 的规则。

于 2012-05-22T14:11:03.883 回答
0

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

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

使用第二个链接 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
于 2012-05-22T14:43:57.217 回答
-1

运行垃圾邮件检测算法(统计算法,如贝叶斯或类似的“学习”算法)。这会或不会帮助你,但如果没有,我真的怀疑你会在这里做出任何有用的逻辑算法。

于 2012-06-03T00:40:11.130 回答