我正在尝试在句子中搜索某些单词(使用PHP)。无论出于何种原因,这些单词可能会被空格分开。 (例如'alpha betical'而不是'alphabetical')。由于原因,我将每个字符组除以该句子中的空格分别与某个正则表达式进行比较。因此,我无法将'alpha betical'与'alphabetical'匹配,因为它会尝试分别匹配'alpha'和'betical'。但是,'alpha'与正则表达式('按字母顺序')部分匹配;如果添加'betical',它将匹配。
我需要像Java Matcher.hitEnd()这样的东西。 (如果在此匹配器执行的最后一个匹配操作中搜索引擎命中了输入的结尾,则返回true。 当此方法返回true时,更多输入可能会更改上次搜索的结果。)This question询问相同的内容,再加上一点,但没有适当的答案。我发现this question得到了解答,但只提供了适用于Java的解决方案(在本段开头提到),而不是PHP。
基本上,如果我将'alpha'
与'/alphabetical/'
匹配,我想要告诉我它至少与正则表达式的一部分匹配。 (我知道在这种情况下,我可以切换它们并将alphabetical
与'/^alpha/'
匹配,但是当我使用它时,正则表达式'/alphabetical/'
会稍微复杂一些,因此不适合开关..想象一下像'/[Aa]lpha-?betical(ly)?|[Ll]exicographical(ly)?/'
)
我知道正则表达式不起作用,只有匹配或没有匹配。有没有办法得到我想要或做的事情我必须以完全不同的方式解决我的问题?
答案 0 :(得分:3)
正则表达式匹配,或者它不匹配。这是一个有限的自动机完成与否。现在肯定有自动化可以在任何节点退出图表并返回"得分",但它们是非标准的。
您可以通过匹配多个正则表达式来添加布尔逻辑。或者通过添加前瞻或后瞻。
为什么不编写你的正则表达式来使空格可选?
/a\s*l\s*p\s*h\s*a\s*b\s*e\s*t\s*i\s*c\s*a\s*l/
匹配各种组合:
alpha betical
al p habet i cal
如果您熟悉通配符/前缀匹配(例如SQL的LIKE功能),则很容易实现。那就够了吗?
考虑一个根本不使用正则表达式的字符串扫描算法的简单实现,但搜索并返回按分数排序的匹配,其中得分是匹配的长度,您甚至可以指定最低分数
示例:
FindLike(haystack: s, needle: "alphabetical", minlen:5);
编写不区分大小写的函数以迭代方式扫描字符串,使用搜索字符串作为前缀匹配,一旦匹配初始字符,迭代两个字符串索引直到一个结束或不匹配,然后返回,应该是直截了当的,或将子字符串添加到结果列表,然后继续。
那就是说,你可能对模糊逻辑或模糊匹配或近似匹配感兴趣。
答案 1 :(得分:3)
你的问题非常广泛,这个答案主要关注这一部分:
如果我匹配“alpha'到' / alphabetical /',我想说些什么 我至少它与正则表达式的一部分匹配。
两个选项
有几种方法可以做到这一点。无论您选择哪种方式,都需要以编程方式构建模式。
常规选项
这是我喜欢使用的一般方式,因为它是直截了当的。它是一系列可选的前瞻,在字符串中越来越远。每个前瞻内部都是一个捕获组。
^(?=(a))?(?=(al))?(?=(alp))?(?=(alph))?(?=(alpha))?(?=(alphab))?(?=(alphabe))?(?=(alphabet))?(?=(alphabeti))?(?=(alphabetic))?(?=(alphabetica))?(?=(alphabetical))?(?=(alphabetical$))?
设置的最高捕获组会告诉您我们匹配的距离。例如,对于alpha
,(?=(alpha))
将成功,并且将设置第5组(以及第1,2,3,4,5组)。
这适用于PCRE。在某些引擎中,您需要包含如下所示的外观:(?:(?=(a)))?
在某些引擎中它根本不起作用。
互斥代币的选项
这是@CasimirEtHippolyte在其他地方建议的另一种方式,它非常紧凑。当令牌不能“吃掉”时,它就会起作用。可以通过以下标记匹配的文本,这是这里的情况。
^(a(l(p(h(a(b(e(t(i(c(a(l($)?)?)?)?)?)?)?)?)?)?)?)?)?
您检查设置了哪些捕获组。设置的最大捕获组会告诉您匹配了多少个字母。