在JavaScript中模拟类SQL
如何在JavaScript中模拟SQL关键字在JavaScript中模拟类SQL,javascript,sql,regex,sql-like,Javascript,Sql,Regex,Sql Like,如何在JavaScript中模拟SQL关键字如 对于那些不知道什么是的人来说,这是一个非常简单的正则表达式,它只支持通配符%,匹配0个或多个字符,以及只匹配一个字符 但是,不可能只执行以下操作: var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null; …因为模式可能包含点、星和任何其他特殊的正则表达式字符。如果要使用正则表达式,可以将字符串的每个字符都用方括号括起来。那么您只
如
对于那些不知道什么是的人来说,这是一个非常简单的正则表达式,它只支持通配符%
,匹配0个或多个字符,以及只匹配一个字符
但是,不可能只执行以下操作:
var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null;
…因为模式可能包含点、星和任何其他特殊的正则表达式字符。如果要使用正则表达式,可以将字符串的每个字符都用方括号括起来。那么您只有几个字符可以转义
但是一个更好的选择可能是截断目标字符串,使其长度与搜索字符串匹配,并检查是否相等。只要您首先转义模式中的正则表达式字符,您所拥有的将起作用。下面是一个例子:
然后,您可以将代码实现为:
likeExpr = RegExp.escape(likeExpr);
var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null;
以下是我使用的函数,基于:
我一直在寻找同一个问题的答案,在阅读Kip的回复后,我得出了以下结论:
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);
}
注2013年11月29日:根据下面的Lucios评论更新了RegExp.test()
性能改进。在Chris Van Opstal的回答中,您应该使用replaceAll而不是replace来替换所有发生的“%”和“\ux”。
参考如何进行replaceAll-Johnny最近来过这里,但这对我很有用,我将其用于spa页面,以避免某些页面在默认页面之后显示结果:
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;
}
功能类(草堆、针){
针=针。分开(',');
var str=haystack.toLowerCase();
var n=-1;
对于(变量i=0;i-1){
返回n;
}
}
返回n;
}
用法是-此处我不想在工具、联系人或主页上显示任何结果-results()是我在此处不显示的函数:
var n = like($data,'tools,contact,home');
//~ alert(n);
if(n < 0){// does not match anything in the above string
results($data);
}
var n=like($data,'tools,contact,home');
//~alert(n);
如果(n<0){//与上述字符串中的任何内容都不匹配
结果(数据);
}
一个老问题,但实际上这里没有好的答案。类TSQL表达式可以包含方括号转义部分,这些转义部分已经几乎是有效的正则表达式,并允许匹配%
和
。例如:
'75%' LIKE '75[%]'
'[foo]' LIKE '[[]foo]' -- ugh
下面是我将LIKE表达式转换为RegExp的函数。输入分为方括号和非方括号部分。方括号部分只需要反斜杠转义,非方括号部分完全转义,而%
和\
指令转换为正则表达式
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');
我想要的东西也能处理转义通配符%
和\
使用\%
和\
的问题
以下是我使用反向查找的解决方案:
//转义RegExp特殊字符
const escapePattern=s=>s.replace(/[-/\\^$*+.()[\]{}]/g,\\$&');
//将ILIKE模式转换为RegExp对象
常量ilikeToRegExp=模式=>
新正则表达式(
`^${escapePattern(模式)}$`
//转换我喜欢的通配符,不匹配转义
.替换(/(?)?
用法:
ilikeToRegExp(“%eLlo WoR%”)。测试('hello world')
//真的
ilikeToRegExp('ello wor')。test('hello world'))
//假的
ilikeToRegExp(“%90\%%”)。测试(“…90%…”)
//真的
我需要这个,在Safari中逃跑和工作(没有负面表情)。以下是我的想法:
/**
* Quotes a string following the same rules as https://www.php.net/manual/function.preg-quote.php
*
* Sourced from https://locutus.io/php/preg_quote/
*
* @param {string} str String to quote.
* @param {?string} [delimiter] Delimiter to also quote.
* @returns {string} The quoted string.
*/
function regexQuote(str, delimiter) {
return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&');
}
/**
* Removes the diacritical marks from a string.
*
* Diacritical marks: {@link https://unicode-table.com/blocks/combining-diacritical-marks/}
*
* @param {string} str The string from which to strip the diacritical marks.
* @returns {string} Stripped string.
*/
function stripDiacriticalMarks(str) {
return unorm.nfkd(str).replaceAll(/[\u0300-\u036f]+/g, '');
}
/**
* Checks if the string `haystack` is like `needle`, `needle` can contain '%' and '_'
* characters which will behave as if used in a SQL LIKE condition. Character escaping
* is supported with '\'.
*
* @param {string} haystack The string to check if it is like `needle`.
* @param {string} needle The string used to check if `haystack` is like it.
* @param {boolean} [ai] Whether to check likeness in an accent-insensitive manner.
* @param {boolean} [ci] Whether to check likeness in a case-insensitive manner.
* @returns {boolean} True if `haystack` is like `needle`, otherwise, false.
*/
function strLike(haystack, needle, ai = true, ci = true) {
if (ai) {
haystack = stripDiacriticalMarks(haystack);
needle = stripDiacriticalMarks(needle);
}
needle = regexQuote(needle, '/');
let tokens = [];
for (let i = 0; i < needle.length; ) {
if (needle[i] === '\\') {
i += 2;
if (i < needle.length) {
if (needle[i] === '\\') {
tokens.push('\\\\');
i += 2;
} else {
tokens.push(needle[i]);
++i;
}
} else {
tokens.push('\\\\');
}
} else {
switch (needle[i]) {
case '_':
tokens.push('.')
break;
case '%':
tokens.push('.*')
break;
default:
tokens.push(needle[i]);
break;
}
++i;
}
}
return new RegExp(`^${tokens.join('')}$`, `u${ci ? 'i' : ''}`).test(haystack);
}
/**
* Escapes a string in a way that `strLike` will match it as-is, thus '%' and '_'
* would match a literal '%' and '_' respectively (and not behave as in a SQL LIKE
* condition).
*
* @param {string} str The string to escape.
* @returns {string} The escaped string.
*/
function escapeStrLike(str) {
let tokens = [];
for (let i = 0; i < str.length; i++) {
switch (str[i]) {
case '\\':
tokens.push('\\\\');
break;
case '%':
tokens.push('\\%')
break;
case '_':
tokens.push('\\_')
break;
default:
tokens.push(str[i]);
}
}
return tokens.join('');
}
/**
*按与相同的规则引用字符串https://www.php.net/manual/function.preg-quote.php
*
*来源于https://locutus.io/php/preg_quote/
*
*@param{string}str要引用的字符串。
*@param{?string}[delimiter]分隔符也要引用。
*@返回带引号的字符串{string}。
*/
函数regexQuote(str,分隔符){
返回(str+'').replace(新的RegExp('[.\\\\+*?\[\\\\^\\]$(){}=!\\;:\\'+(分隔符\\\\''+'-]','g'),'\$&');
}
/**
*从字符串中删除变音符号。
*
*变音符号:{@linkhttps://unicode-table.com/blocks/combining-diacritical-marks/}
*
*@param{string}str用于去除变音符号的字符串。
*@返回{string}条带字符串。
*/
功能条带区分标记(str){
返回unorm.nfkd(str.replaceAll(/[\u0300-\u036f]+/g');
}
/**
*检查字符串'haystack'是否类似于'needle','needle'可以包含“%”和“\u1”
*行为类似于在类似SQL的条件下使用的字符。字符转义
*由“\”支持。
*
*@param{string}干草堆叠字符串以检查它是否像“针”。
*@param{string}用于检查haystack是否与之类似的字符串。
*@param{boolean}[ai]是否以不区分重音的方式检查相似性。
*@param{boolean}[ci]是否以不区分大小写的方式检查相似性。
*@如果'haystack'类似于'needle',则返回{boolean}True,否则返回false。
*/
函数strLike(草堆、针、ai=true、ci=true){
如果(ai){
干草堆=条带临界标线(干草堆);
针=条纹色标(针);
}
针=regexQuote(针“/”);
让令牌=[];
对于(设i=0;ivar n = like($data,'tools,contact,home');
//~ alert(n);
if(n < 0){// does not match anything in the above string
results($data);
}
'75%' LIKE '75[%]'
'[foo]' LIKE '[[]foo]' -- ugh
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');
/**
* Quotes a string following the same rules as https://www.php.net/manual/function.preg-quote.php
*
* Sourced from https://locutus.io/php/preg_quote/
*
* @param {string} str String to quote.
* @param {?string} [delimiter] Delimiter to also quote.
* @returns {string} The quoted string.
*/
function regexQuote(str, delimiter) {
return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&');
}
/**
* Removes the diacritical marks from a string.
*
* Diacritical marks: {@link https://unicode-table.com/blocks/combining-diacritical-marks/}
*
* @param {string} str The string from which to strip the diacritical marks.
* @returns {string} Stripped string.
*/
function stripDiacriticalMarks(str) {
return unorm.nfkd(str).replaceAll(/[\u0300-\u036f]+/g, '');
}
/**
* Checks if the string `haystack` is like `needle`, `needle` can contain '%' and '_'
* characters which will behave as if used in a SQL LIKE condition. Character escaping
* is supported with '\'.
*
* @param {string} haystack The string to check if it is like `needle`.
* @param {string} needle The string used to check if `haystack` is like it.
* @param {boolean} [ai] Whether to check likeness in an accent-insensitive manner.
* @param {boolean} [ci] Whether to check likeness in a case-insensitive manner.
* @returns {boolean} True if `haystack` is like `needle`, otherwise, false.
*/
function strLike(haystack, needle, ai = true, ci = true) {
if (ai) {
haystack = stripDiacriticalMarks(haystack);
needle = stripDiacriticalMarks(needle);
}
needle = regexQuote(needle, '/');
let tokens = [];
for (let i = 0; i < needle.length; ) {
if (needle[i] === '\\') {
i += 2;
if (i < needle.length) {
if (needle[i] === '\\') {
tokens.push('\\\\');
i += 2;
} else {
tokens.push(needle[i]);
++i;
}
} else {
tokens.push('\\\\');
}
} else {
switch (needle[i]) {
case '_':
tokens.push('.')
break;
case '%':
tokens.push('.*')
break;
default:
tokens.push(needle[i]);
break;
}
++i;
}
}
return new RegExp(`^${tokens.join('')}$`, `u${ci ? 'i' : ''}`).test(haystack);
}
/**
* Escapes a string in a way that `strLike` will match it as-is, thus '%' and '_'
* would match a literal '%' and '_' respectively (and not behave as in a SQL LIKE
* condition).
*
* @param {string} str The string to escape.
* @returns {string} The escaped string.
*/
function escapeStrLike(str) {
let tokens = [];
for (let i = 0; i < str.length; i++) {
switch (str[i]) {
case '\\':
tokens.push('\\\\');
break;
case '%':
tokens.push('\\%')
break;
case '_':
tokens.push('\\_')
break;
default:
tokens.push(str[i]);
}
}
return tokens.join('');
}
strLike('Hello I ended up writing a function based on a few answers here that worked pretty well for me. I needed something that would preserve the "startswith%" and "%endswith" syntax, and returns no matches for an empty search string.
function sqlLIKE(target, likeExp) {
let regex = likeExp
.replaceAll(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1')
.replaceAll("%", ".*")
.replaceAll("_", ".");
if (likeExp.charAt(0) !== '%' || !likeExp.includes('%')) regex = `^${regex}`;
if (likeExp.charAt(likeExp.length - 1) !== '%' || !likeExp.includes('%')) regex = `${regex}$`;
return new RegExp(regex).exec(target) !== null;
}