正则表达式通配符匹配

Rad*_*zea 22 java regex

我有一个大约12万个英语单词的列表(基本上是语言中的每个单词).

我需要一个正则表达式,允许使用通配符字符搜索这些单词,aka *?.

几个例子:

  • 如果用户搜索m?st*,它将匹配例如mastermistermistery.
  • 如果用户搜索*ind(任何结尾的单词ind),它将匹配windbindblindgrind.

现在,大多数用户(尤其是那些不熟悉正则表达式的用户)知道它?只是一个字符*的替代品,而是0,1个或更多字符的替代品.我绝对想基于此构建我的搜索功能.

我的问题是:如何将用户输入的内容(m?st*例如)转换为正则表达式?

我在网上搜索(显然包括这个网站),我找到的所有内容都是试图教我太多的教程或者有些相似的问题,但还不足以为我自己的问题提供答案.

所有我能想出的是,我不得不更换?..因此m?st*变得m.st*.但是,我不知道要替换什么*.

任何帮助将不胜感激.谢谢.

PS:我对正则表达式完全陌生.我知道它们有多么强大,但我也知道它们很难学.所以我从来没有花时间去做它......

gno*_*med 16

除非你想要一些有趣的行为,否则我建议你使用\w而不是.

. 匹配您可能不希望它执行的空格和其他非单词符号.

因此,我将代替?\w和替换*\w*

此外,如果您想*匹配至少一个字符,请\w+改为替换它.这意味着ben*将匹配bendbending,但没有ben-它是由你,只是取决于你的需求是什么.

  • @Gareth你,我看到了.只是想我会提供额外的信息. (2认同)

len*_*non 7

看看这个库:https://github.com/alenon/JWildcard

它通过正则表达式引号包装所有非通配符特定部分,因此不需要特殊的字符处理:此通配符:

"mywil?card*"
Run Code Online (Sandbox Code Playgroud)

将转换为此正则表达式字符串:

"\Qmywil\E.\Qcard\E.*"
Run Code Online (Sandbox Code Playgroud)

如果您希望将通配符转换为正则表达式字符串,请使用:

JWildcard.wildcardToRegex("mywil?card*");
Run Code Online (Sandbox Code Playgroud)

如果您想直接检查匹配,可以使用:

JWildcard.matches("mywild*", "mywildcard");
Run Code Online (Sandbox Code Playgroud)

默认通配符规则是"?" - >"."," " - >". ",但如果您愿意,可以通过简单地定义新规则来更改默认行为.

JWildcard.wildcardToRegex(wildcard, rules, strict);
Run Code Online (Sandbox Code Playgroud)

您可以使用来自Bintray JCenter的maven或gradle直接下载源代码:https://bintray.com/yevdo/jwildcard/jwildcard

Gradle方式:

compile 'com.yevdo:jwildcard:1.2'
Run Code Online (Sandbox Code Playgroud)

Maven方式:

<dependency>
  <groupId>com.yevdo</groupId>
  <artifactId>jwildcard</artifactId>
  <version>1.2</version>
  <type>pom</type>
</dependency>
Run Code Online (Sandbox Code Playgroud)

  • 感谢您在库中未包含任何传递依赖项! (2认同)

NPE*_*NPE 6

更换?.*.*.


Boh*_*dan 6

这是一种将通配符转换为正则表达式的方法:

  1. 将所有特殊字符 ([{\ ^ - = $!|]}).+与\ 前置,以便它们作为字符匹配,不会使用户遇到意外情况.你也可以将它包含在\ Q(开始引用)和\ E(结束它)中.另见关于安全性的段落.
  2. 用*S*替换*通配符
  3. 替换?带\ S的通配符
  4. 可选:使用^预先添加模式- 这将强制与开头完全匹配.
  5. 可选:将$附加到模式 - 这将强制与结束完全匹配.

    \ S - 代表非空格字符,发生零次或多次.

如果在*或+之后有匹配的字符,请考虑使用不情愿(非贪婪)量词.这可以通过添加来完成在*或+之后这样:\ S*?\ S*+?

考虑安全性:用户将向您发送要运行的代码(因为正则表达式也是一种代码,用户字符串用作正则表达式).您应该避免将未转义的正则表达式传递给应用程序的任何其他部分,并且仅用于过滤通过其他方式检索的数据.因为如果您这样做,用户可以通过提供带有通配符字符串的不同正则表达式来影响代码的速度 - 这可以用于DoS攻击.

示例显示类似模式的执行速度:

seq 1 50000000 > ~/1
du -sh ~/1
563M
time grep -P '.*' ~/1 &>/dev/null
6.65s
time grep -P '.*.*.*.*.*.*.*.*' ~/1 &>/dev/null
12.55s
time grep -P '.*..*..*..*..*.*' ~/1 &>/dev/null
31.14s
time grep -P '\S*.\S*.\S*.\S*.\S*\S*' ~/1 &>/dev/null
31.27s
Run Code Online (Sandbox Code Playgroud)

我建议不要使用.*只是因为它可以匹配任何东西,通常用空格分隔.