如何实现像“LIKE”这样的SQL java中的运算符?
我需要一个 java 中的比较器,它与 sql 'like' 运算符具有相同的语义。 例如:
myComparator.like("digital","%ital%");
myComparator.like("digital","%gi?a%");
myComparator.like("digital","digi%");
应该评估为 true,并且
myComparator.like("digital","%cam%");
myComparator.like("digital","tal%");
应该评估为 false。 有什么想法如何实现这样的比较器或者有人知道具有相同语义的实现吗? 这可以使用正则表达式来完成吗?
I need a comparator in java which has the same semantics as the sql 'like' operator.
For example:
myComparator.like("digital","%ital%");
myComparator.like("digital","%gi?a%");
myComparator.like("digital","digi%");
should evaluate to true, and
myComparator.like("digital","%cam%");
myComparator.like("digital","tal%");
should evaluate to false. Any ideas how to implement such a comparator or does anyone know an implementation with the same semantics? Can this be done using a regular expression?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
.* 将匹配正则表达式中的任何字符,
我认为 java 语法是
对于单字符匹配,只需使用一个点。
为了匹配实际的点,将其转义为斜杠点
.* will match any characters in regular expressions
I think the java syntax would be
And for the single character match just use a single dot.
And to match an actual dot, escape it as slash dot
正则表达式是最通用的。 但是,某些 LIKE 函数可以在没有正则表达式的情况下形成。 例如
Regular expressions are the most versatile. However, some LIKE functions can be formed without regular expressions. e.g.
是的,这可以通过正则表达式来完成。 请记住,Java 的正则表达式与 SQL 的“like”具有不同的语法。 您将使用“
.*
”而不是“%
”,并且您将使用“.*”而不是“
”。?
”。让它变得有些棘手的是,您还必须转义 Java 视为特殊的任何字符。 由于您试图使其类似于 SQL,因此我猜测
^$[]{}\
不应出现在正则表达式字符串中。 但在进行任何其他替换之前,您必须将“.
”替换为“\\.
”。 (编辑:Pattern.quote(String)
通过用“\Q
”和“\E”包围字符串来转义所有内容
”,这将导致表达式中的所有内容都被视为文字(根本没有通配符)。所以您肯定不想使用它。)此外,正如 Dave Webb说,你还需要忽略大小写。
考虑到这一点,下面是它的示例:
Yes, this could be done with a regular expression. Keep in mind that Java's regular expressions have different syntax from SQL's "like". Instead of "
%
", you would have ".*
", and instead of "?
", you would have ".
".What makes it somewhat tricky is that you would also have to escape any characters that Java treats as special. Since you're trying to make this analogous to SQL, I'm guessing that
^$[]{}\
shouldn't appear in the regex string. But you will have to replace ".
" with "\\.
" before doing any other replacements. (Edit:Pattern.quote(String)
escapes everything by surrounding the string with "\Q
" and "\E
", which will cause everything in the expression to be treated as a literal (no wildcards at all). So you definitely don't want to use it.)Furthermore, as Dave Webb says, you also need to ignore case.
With that in mind, here's a sample of what it might look like:
我能找到的每个 SQL 参考都说“任何单个字符”通配符是下划线 (
_
),而不是问号 (?
)。 这稍微简化了事情,因为下划线不是正则表达式元字符。 但是,由于 mmyers 给出的原因,您仍然无法使用Pattern.quote()
。 当我之后可能想编辑正则表达式时,我有另一种方法可以转义它们。 有了这个,like()
方法就变得非常简单:如果您确实想使用
?
作为通配符,最好的选择是将其从quotemeta()
方法中的元字符列表。 替换其转义形式 -replace("\\?", ".")
- 并不安全,因为原始表达式中可能存在反斜杠。这给我们带来了真正的问题:大多数 SQL 风格似乎都支持
[az]
和[^jm]
或[!jm] 形式的字符类
,并且它们都提供了一种转义通配符的方法。 后者通常通过ESCAPE
关键字来完成,它允许您每次定义不同的转义字符。 正如您可以想象的那样,这使事情变得相当复杂。 转换为正则表达式可能仍然是最好的选择,但解析原始表达式会困难得多 - 事实上,您要做的第一件事就是形式化类似LIKE
的语法他们自己。Every SQL reference I can find says the "any single character" wildcard is the underscore (
_
), not the question mark (?
). That simplifies things a bit, since the underscore is not a regex metacharacter. However, you still can't usePattern.quote()
for the reason given by mmyers. I've got another method here for escaping regexes when I might want to edit them afterward. With that out of the way, thelike()
method becomes pretty simple:If you really want to use
?
for the wildcard, your best bet would be to remove it from the list of metacharacters in thequotemeta()
method. Replacing its escaped form --replace("\\?", ".")
-- wouldn't be safe because there might be backslashes in the original expression.And that brings us to the real problems: most SQL flavors seem to support character classes in the forms
[a-z]
and[^j-m]
or[!j-m]
, and they all provide a way to escape wildcard characters. The latter is usually done by means of anESCAPE
keyword, which lets you define a different escape character every time. As you can imagine, this complicates things quite a bit. Converting to a regex is probably still the best option, but parsing the original expression will be much harder--in fact, the first thing you would have to do is formalize the syntax of theLIKE
-like expressions themselves.要在java中实现sql的LIKE函数,你不需要正则表达式
它们可以通过以下方式获得:
To implement LIKE functions of sql in java you don't need regular expression in
They can be obtained as:
Java 字符串有 .startsWith() 和 .contains() 方法,它们可以帮助您完成大部分工作。 对于任何更复杂的事情,您必须使用正则表达式或编写自己的方法。
Java strings have .startsWith() and .contains() methods which will get you most of the way. For anything more complicated you'd have to use regex or write your own method.
您可以将
'%string%'
转换为contains()
、'string%'
到startsWith()
和'%string"'
到endsWith()
。您还应该运行
toLowerCase()
在字符串和模式上都为 < code>LIKE 不区分大小写。则不确定如何处理
'%string%other%'
不过,如果您使用正则表达式,
%
字符之前引用字符串LIKE
字符串中的转义字符You could turn
'%string%'
tocontains()
,'string%'
tostartsWith()
and'%string"'
toendsWith()
.You should also run
toLowerCase()
on both the string and pattern asLIKE
is case-insenstive.Not sure how you'd handle
'%string%other%'
except with a Regular Expression though.If you're using Regular Expressions:
%
charactersLIKE
String可能会对你有帮助
may be help you
Apache Cayanne ORM 有一个“内存评估”,
它可能不起作用对于未映射的对象,但看起来很有希望:
Apache Cayanne ORM has an "In memory evaluation"
It may not work for unmapped object, but looks promising:
比较器 和 Comparable 接口在这里可能不适用。 它们处理排序,并返回有符号或 0 的整数。您的操作是查找匹配项,并返回 true/false。 那不一样。
The Comparator and Comparable interfaces are likely inapplicable here. They deal with sorting, and return integers of either sign, or 0. Your operation is about finding matches, and returning true/false. That's different.
http://josql.sourceforge.net/ 有您所需要的。 查找 org.josql.expressions.LikeExpression。
http://josql.sourceforge.net/ has what you need. Look for org.josql.expressions.LikeExpression.
我不太清楚贪婪的问题,但如果它适合你,请尝试一下:
i dont know exactly about the greedy issue, but try this if it works for you:
我有一个类似的要求,经过一些修改可能会有所帮助,这里是代码:
public class TestLikeInJava {
}
I have a similar requirement, which may help, with some modifications, here is the code:
public class TestLikeInJava {
}
请查看 https://github.com/hrakaroo/glob-library-java。
它是 Java 中的一个零依赖库,用于进行 glob(和类似 sql)类型的比较。 在大型数据集上,它比转换为正则表达式更快。
基本语法
Check out https://github.com/hrakaroo/glob-library-java.
It's a zero dependency library in Java for doing glob (and sql like) type of comparisons. Over a large data set it is faster than translating to a regular expression.
Basic syntax
这是我对此的看法,它是用 Kotlin 编写的,但可以轻松转换为 Java:
它可能不是这里所有解决方案中性能最高的,但它可能是最准确的。
它忽略除 % 和 _ 之外的所有其他正则表达式元字符,并且还支持使用斜杠转义它们。
This's my take on this, it's in Kotlin but can be converted to Java with little effort:
It might not be the most performant of all the solutions here, but it's probably the most accurate.
It ignores all the other Regex metacharacters other than % and _ and also supports escaping them with a slash.
来自 https://www.tutorialspoint.com/java/java_string_matches.htm
from https://www.tutorialspoint.com/java/java_string_matches.htm
好吧,这是一个有点奇怪的解决方案,但我认为仍然应该提及。
我们可以利用任何数据库中已有的现有实现,而不是重新创建类似的机制!
(唯一的要求是,您的应用程序必须有权访问任何数据库)。
每次只需运行一个非常简单的查询,根据同类比较的结果返回 true 或 false。 然后执行查询,直接从数据库中读取答案!
对于 Oracle 数据库:
对于 MS SQL Server
您所需要做的就是用绑定参数替换“StringToSearch”和“LikeSequence”,并设置要检查的值。
Ok this is a bit of a weird solution, but I thought it should still be mentioned.
Instead of recreating the like mechanism we can utilize the existing implementation already available in any database!
(Only requirement is, your application must have access to any database).
Just run a very simple query each time,that returns true or false depending on the result of the like's comparison. Then execute the query, and read the answer directly from the database!
For Oracle db:
For MS SQL Server
All you have to do is replace "StringToSearch" and "LikeSequence" with bind parameters and set the values you want to check.