【问题标题】:Pattern matching on a string that already has wildcards in it对已包含通配符的字符串进行模式匹配
【发布时间】:2013-11-07 18:10:25
【问题描述】:

我有一个场景,我想在已经包含通配符的字符串上使用通配符模式进行搜索。用我的话来说,我会说这是一种 2 路模式匹配要求。

输入和模式字符串可以具有以下通配符之一/两个 - ?表示单个字符,% 表示零个或多个字符。假设这些是输入和模式字符串中仅允许使用的 2 个通配符。

例如:

bool IsMatch(string input, string pattern) //如果输入字符串与模式匹配则返回True,否则返回False。

IsMatch("XYZ%", "?Y%") // 应该返回 True

IsMatch("YY?", "?Y%") // 应该返回 True - 输入字符串中的最后一个字符需要一个字符,因为模式匹配 Y 之后的零个或多个字符(这意味着它包括一个字符匹配)

IsMatch("X123", "?Y%") // 应该返回 False - 模式期望的输入字符串中缺少 Y

IsMatch("?Y%", "?Y%")// 应该返回True

IsMatch("%", "?Y%")// 应该返回 True - 输入字符串有一个通配符 % 表示零个或多个字符,也可以有任何字符。在某种程度上,它本身就是一种模式,代表任何大小的任何东西。

我能够找到仅讨论对非通配符字符串执行通配符模式匹配的文章(例如:Regex)。我正在寻找关于算法的指针/想法,因为当我开始放下它时,我很难想出一种可以进行这种匹配的算法。感谢您的投入。

【问题讨论】:

  • 你如何计算这些匹配? X 和 Y 匹配,%(通常在数据库中使用但不在正则表达式中使用的通配符)与输入的其余部分(Z5%)匹配,但在那之后,您的搜索模式需要 HH?123 不是在输入中找到。或者您是否认为这些与输入末尾的通配符匹配?这使您的问题是“这些正则表达式是否都可以匹配的输入?”这不好回答。
  • @SQB XY 两者都匹配,第一个中的Z5 第二个匹配%,第二个HH?123 匹配第一个%。一种双向匹配。
  • @iamnotmaynard 是的,我很害怕。正如我所说,这提出了真正的问题'是否有 any 输入这两个正则表达式都可以匹配?'
  • @SQB 输入字符串存储在数据库中,我获取并与搜索/模式字符串进行比较。期望是,在我的应用程序 UI 中,如果用户使用此搜索/模式字符串进行搜索,我的应用程序(C#.net)应匹配从数据库中获取的此输入字符串并将此输入字符串显示给用户。跨度>
  • 您必须清楚地定义您使用的模式匹配语言(或指向在线内容)并提供一些搜索模式和各种输入 对于每个——并解释为什么它是或不被认为是匹配的。只有这样,任何人才能告诉你这是否可以用正则表达式来完成。

标签: c# regex wildcard


【解决方案1】:

正如我在评论中针对最一般情况所写的那样,您必须创建两个表达式的最小确定性有限自动机并比较这两个自动机。话虽如此,您的问题可能有一个蛮力/穷人的解决方案。

根据您的示例,您似乎有兴趣查看输入/模式之一是否与另一个生成的所有字符串匹配。

IsMatch("XYZ%", "?Y%") // returns true because ?Y% matches a superset of strings matched by "XYZ%"
IsMatch("%", "?Y%") // returns true because "%" matches a superset of "?Y%"

您可以检查input 是否确实匹配pattern 生成的字符串子集,只要

  • 你真的可以把自己限制在 % 和 ?指定的运算符
  • 您的输入/模式字符串相当短 - 更具体地说,输入或模式中 % 的出现少于大约 20 次。

基本思想是您为input 生成一个代表字符串列表,并使用您最喜欢的正则表达式引擎将每个字符串与模式匹配。如果所有代表都匹配 - input 匹配 pattern 的子集。 IsSubset的这个算法可以描述如下

let c = some character not in `pattern` (lexically speaking)
let searchString = replace all occurences of '?' in input with c
add searchString to setOfSearchStrings
foreach occurence of '%' in input
    foreach str in setOfSearchStrings
        replace str with two strings - {str with c in place of '%', str without the '%'}

foreach str in setOfSearchStrings
   if str doesn't "regex" match with pattern 
       return false

return true

例如,如果输入是 ?X%YZ% 并且 pattern 不包含字符 A,则生成的列表将是
AXYZ
AXYZA
阿萨伊兹
阿萨伊扎

很容易看出,这个列表中的字符串数量是 2^n,其中 n 是输入中 '%' 的数量。

此外,交换参数的顺序并反过来找出关系也很容易。所以实际上你的

IsMatch(input,pattern) = IsSubset(input,pattern) || IsSubset(pattern,input)

【讨论】:

  • 您好 Hawk,非常感谢您分享您的想法并提供详细的解释。这是一个非常好的主意,肯定会帮助我思考这个方向的解决方案。
猜你喜欢
  • 2022-06-10
  • 2017-12-03
  • 1970-01-01
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-08
相关资源
最近更新 更多