可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How can I emulate the SQL keyword LIKE
in JavaScript?
For those of you who don't know what LIKE
is, it's a very simple regex which only supports the wildcards %
, which matches 0 or more characters, and _
which matches exactly one character.
However, it's not just possible to do something like:
var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null;
...because the pattern might contain dots, stars and any other special regex characters.
回答1:
What you have will work as long as you first escape the regex characters in your pattern. Below is one example from Simon Willison’s blog:
RegExp.escape = function(text) {
if (!arguments.callee.sRE) {
var specials = [
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\'
];
arguments.callee.sRE = new RegExp(
'(\\' + specials.join('|\\') + ')', 'g'
);
}
return text.replace(arguments.callee.sRE, '\\$1');
}
You could then implement your code as:
likeExpr = RegExp.escape(likeExpr);
var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null;
回答2:
I was looking for an answer the same question and came up with this after reading Kip's reply:
String.prototype.like = function(search) {
if (typeof search !== 'string' || this === null) {return false; }
// Remove special chars
search = search.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1");
// Replace % and _ with equivalent regex
search = search.replace(/%/g, '.*').replace(/_/g, '.');
// Check matches
return RegExp('^' + search + '$', 'gi').test(this);
}
You can then use it as follows (note that it ignores UPPER/lower case):
var url = 'http://www.mydomain.com/page1.aspx';
console.log(url.like('%mydomain.com/page_.asp%')); // true
NOTE 29/11/2013: Updated with RegExp.test()
performance improvement as per Lucios comment below.
回答3:
Here's a function I use, based on PHP's preg_quote function:
function regex_quote(str) {
return str.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1");
}
So your line would now be:
var match = new RegEx(regex_quote(likeExpr).replace("%", ".*").replace("_", ".")).exec(str) != null;
回答4:
If you want to use a regex, you can wrap each character of the string in square-brackets. Then you only have a few characters to escape.
But a better option might be to truncate the target strings so the length matches your search string and check for equality.
回答5:
An old question but there are actually no good answers here. TSQL LIKE expressions can contain square-bracket escaped sections that are already almost valid regular expressions and allow for matching %
and _
. E.g.:
'75%' LIKE '75[%]'
'[foo]' LIKE '[[]foo]' -- ugh
Here's my function to convert a LIKE expression into a RegExp. The input is split into square-bracket and non-square-bracket sections. The square-bracket sections just need backslash escaping and the non-square-bracket sections are fully escaped while the %
and _
directives are converted to regular expressions.
const likeRegExp = (expression, caseSensitive = false) =>
new RegExp(`^${
expression.split(/(\[.+?\])/g)
.map((s, i) => i % 2 ?
s.replace(/\\/g, '\\\\') :
s.replace(/[-\/\\^$*+?.()|[\]{}%_]/g, m => {
switch(m) {
case '%': return '.*';
case '_': return '.';
default: return `\\${m}`;
}
})
).join('')
}$`, caseSensitive ? '' : 'i');
回答6:
In Chris Van Opstal's answer you should use replaceAll instead of replace to replace all occurrances of '%' and '_'.
Reference to how to do replaceAll - here
回答7:
Johnny come lately here but this works for me I use it for my spa pages to avoid certain pages showing results after the default page:
function like(haystack,needle){
needle = needle.split(',');
var str = haystack.toLowerCase();
var n = -1;
for(var i=0;i<needle.length;i++){
n = str.search(needle[i]);
if(n > -1){
return n;
}
}
return n;
}
usage is - here I want to not show any results on the tools,contact or home pages - results() is a function I do not show here:
var n = like($data,'tools,contact,home');
//~ alert(n);
if(n < 0){// does not match anything in the above string
results($data);
}