【问题标题】:Can I match the beginnings of words?我可以匹配单词的开头吗?
【发布时间】:2012-06-11 20:50:42
【问题描述】:

我正在为用户构建一个小型过滤器实用程序来快速过滤项目列表,并且我想按顺序匹配单词的开头,最好使用正则表达式:

考虑一个用户试图找到标记为here is some text的项目。

  • 我已经知道如何让它匹配任何一个单词的开头:

herhere 是一些文字 — \bher
so — 这里是 so me text — \bso
ext不匹配\bext

  • 而且我知道如何让它匹配几个单词的首字母:

histhere is some text — @ 987654325@
hth是一些 text — \bh.*?\bt

  • 我需要的是能够匹配几个单词的前n 字符:

hersthere 是 some text
iso > - 这里s 所以我的文字
teh - 不匹配

我这样做是因为我的项目通常包含 intialisms,用户可能会键入 usc 来尝试快速拉出 USA、C加利福尼亚州

我正在为每个输入重写模式,所以我可以做一些工作,这在案例 #2 中是必要的。我正在寻找一种能够随字符数线性扩展的解决方案,无论是模式复杂度还是总复杂度。

鉴于这些限制,我匹配这些字符串的最佳选择是什么?

【问题讨论】:

    标签: regex pattern-matching


    【解决方案1】:

    我认为标准的正则表达式库无法做到这一点。

    但是考虑到您的限制,您应该能够编写自己的解析器来进行匹配。保留一堆模式,然后从头到尾扫描输入文本。您需要跟踪的唯一状态是前一个字符是边界还是从堆栈中取出项目。如果你在没有清空堆栈的情况下到达输入的末尾,那就是不匹配。

    在伪代码中:

    pattern = "herst"
    input = "here is some text"
    state = true
    until input.empty? or pattern.empty? do
      if input[0] == pattern[0] and state
        pattern.shift!
      else
        state = is_boundary(input[0])
      endif
      input.shift!
    done
    return pattern.empty?
    

    【讨论】:

    • 我正在考虑编写自己的解析器,但您能说得更详细一点吗?我的印象是我必须跟踪的不仅仅是单词边界。
    • 给出的例子完全不在我的脑海中。那里没有提供任何保证,但我认为它会像那样工作。
    • (先发制人的细节!太棒了。)如果 Wrikken 的怪物过于密集,我会实现这个。
    • 呵呵。必须是时区差异。
    【解决方案2】:

    像这样的怪物:

     \bh(.*?\b)?e(.*?\b)?r(.*?\b)?s(.*?\b)?t
    

    基本上,每个字母要么在前一个字母之前,要么以一个以单词边界(.*?\b) 结尾的随机序列开头。所以,我们用? 使这个随机序列+ \b 成为可选的。所以,在所有字母之间用(.*?\b)? 分开应该可以。

    【讨论】:

    • 怪物,是的,但它完美地满足了我的所有要求。希望性能不会成为问题..
    • 性能方面,如果您的正则表达式实现支持它,您可以使用(?:.*?\b)? 使(.*?\b)? 不捕获,这样可以节省一点资源。但我更担心字符串较长的回溯量。
    • 我只是从列表中搜索相对较小的项目(几十个字符),所以希望回溯不会成为一个大问题。
    【解决方案3】:

    使用纯正则表达式以灵活的方式做到这一点是很困难的,如果不是不可能的话。我想到的一种可能的方法是首先尝试使用单词边界进行简单的正则表达式匹配,就像您已经完成的那样,然后生成一组所有可能的前缀和后缀对并与它们进行匹配。但是,如果您希望能够匹配字符串中任意两个以上的单独单词,您可能应该编写一个简单的函数来遍历正在搜索的字符串,尝试匹配查询字符串中的最长前缀。一旦找到最长的前缀,就继续搜索字符串中的下一个单词,并尝试匹配查询的其余部分(即减去已经匹配的前缀),并继续执行此操作直到整个查询已匹配,或搜索到的字符串结束。这应该很容易递归实现。

    【讨论】:

      【解决方案4】:

      尝试使用^<myregex> 作为字符串的开头,<myregex>$ 作为结尾。

      【讨论】:

      • ...这不是问题是关于什么的。
      猜你喜欢
      • 2021-02-10
      • 2014-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-12
      • 1970-01-01
      相关资源
      最近更新 更多