从字符串集派生 RegExp

Posted

技术标签:

【中文标题】从字符串集派生 RegExp【英文标题】:Derive RegExp from set of strings 【发布时间】:2012-08-03 11:06:30 【问题描述】:

想象有一组任意字符串。我们现在假设除了几个后续字符之外它们都是相等的(如果这个假设不成立,我可以返回错误)。我现在想派生一个正则表达式来识别字符串中不同的部分。

输入: “你好 Alice,我是 Bob。”、“你好 John,我是 Bob。”、“你好 Josh,我是 Bob。” 输出: “你好 (.+),我是 Bob。” 输入: “星期一”、“树”、“狗” 输出: 错误

也许找到longest common substrings 或Levenshtein distance 会有所帮助?我还不确定其中一个是否真的适用于我的问题或如何使用它们来解决它。

【问题讨论】:

既然是作业,我会尽量给出一个更“周到”的提示。我不确定您在基本计算理论方面的背景是什么,但是将此类问题想象为 DFA(或者,在这种情况下,可能是等效的 NFA)通常会有所帮助。尝试创建一个产生正确结果的状态图并将其转换为正则表达式。 不知道为什么这被标记为作业。它不是!无论如何......我还看不出这与自动机有什么关系,你能更详细地解释一下吗?我也不明白为什么我的例子与我的问题不符。如果你能告诉我你的意思,我会努力改进我的问题。 【参考方案1】:

您遇到了问题并决定使用正则表达式来解决它——现在您遇到了两个问题。 :-)

别开玩笑了,您可以将其分解为两个步骤:

    识别字符串之间的差异。 查看所有差异并找出匹配它们的正则表达式。

对于 (1),使用您的语言中的差异计算库(如 Python 中的 difflib)来查找两个字符串之间相同区域的列表是一个问题。如果所有字符串都有公共段,则将 string-1 与每个 string-[2..N] 进行比较以分析生成的相同块(您必须聪明地比较每个块的内容及其相对于其他相同块的位置块)。提取和记录相同块之间的文本。

对于您的示例,每次比较时都会得到两个相同的块:"Hello "", I'm Bob."。 相同块之间的文本将是这些字符串:"Alice""John""Josh"

对于 (2),最简单的解决方案是将您的发现组合成一个非常字面的正则表达式,其中包含:

Hello + (Alice|John|Josh) + , I'm Bob.

或者,用.* 替换all 字符串中相同相同块之间的任何段。考虑让它成为一个非贪婪的匹配——.*?

我不了解自动机理论,无法在 DFA/NFA 方面为您提供帮助,但如果您需要更高的精度,这是一个可靠的方向。

【讨论】:

以上是关于从字符串集派生 RegExp的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 RegExp 替换

regexp_like 选择属性字符串包含多个不同单词的行

Netezza 和 Regexp:如何从字符串中删除所有非字母

使用 postgres regexp_replace() 替换字符串中的整数

RegExp 从管道分隔的字符串中提取值

Regexp_replace :从 Oracle 中的“+”分隔字符串中删除重复项 [重复]