在 Javascript 中提取 JPA 命名参数
Extract JPA Named Parameters in Javascript
我正在尝试在 Javasacript 中提取 JPA 命名参数。这是我能想到的算法
const notStrRegex = /(?<![\S"'])([^"'\s]+)(?![\S"'])/gm
const namedParamCharsRegex = /[a-zA-Z0-9_]/;
/**
* @returns array of named parameters which,
* 1. always begins with :
* 2. the remaining characters is guranteed to be following {@link namedParamCharsRegex}
*
* @example
* 1. "select * from a where id = :myId3;" -> [':myId3']
* 2. "to_timestamp_tz(:FROM_DATE, 'YYYY-MM-DD\"T\"HH24:MI:SS')" -> [':FROM_DATE']
* 3. "TO_CHAR(ep.CHANGEDT,'yyyy=mm-dd hh24:mi:ss')" -> []
*/
export function extractNamedParam(query: string): string[] {
return (query.match(notStrRegex) ?? [])
.filter((word) => word.includes(':'))
.map((splittedWord) => splittedWord.substring(splittedWord.indexOf(':')))
.filter((splittedWord) => splittedWord.length > 1) // ignore ":"
.map((word) => {
// i starts from 1 because word[0] is :
for (let i = 1; i < word.length; i++) {
const isAlphaNum = namedParamCharsRegex.test(word[i]);
if (!isAlphaNum) return word.substring(0, i);
}
return word;
});
}
我的灵感来自于
过滤掉包含在 single/double 个引号中的所有字符。
虽然上面的代码完成了上面的 3 个用例。
但是当用户输入
const testStr = '"user input invalid string \' :shouldIgnoreThisNamedParam \' in a string"'
extractNamedParam(testStr) // should return [] but it returns [":shouldIgnoreThisNamedParam"] instead
我确实访问了 hibernate 的源代码,看看那里是如何提取命名参数的,但我找不到执行这项工作的算法。请帮忙。
你可以使用
/"[^\"]*(?:\[\w\W][^\"]*)*"|'[^\']*(?:\[\w\W][^\']*)*'|(:\w+)/g
仅获取第 1 组值。参见regex demo。正则表达式匹配 single/double 引号之间的字符串并捕获 :
+ 所有其他上下文中的一个或多个单词字符。
查看 JavaScript 演示:
const re = /"[^\"]*(?:\[\w\W][^\"]*)*"|'[^\']*(?:\[\w\W][^\']*)*'|(:\w+)/g;
const text = "to_timestamp_tz(:FROM_DATE, 'YYYY-MM-DD\"T\"HH24:MI:SS')";
let matches=[], m;
while (m=re.exec(text)) {
if (m[1]) {
matches.push(m[1]);
}
}
console.log(matches);
详情:
"[^\"]*(?:\[\w\W][^\"]*)*"
- "
,然后 "
和 \
([^"\]*
) 以外的零个或多个字符,然后是零个或多个重复任何转义字符 (\[\w\W]
) 后跟除 "
和 \
以外的零个或多个字符,然后是 "
|
- 或
'[^\']*(?:\[\w\W][^\']*)*'
- '
,然后 '
和 \
([^'\]*
) 以外的零个或多个字符,然后是零个或多个重复任何转义字符 (\[\w\W]
) 后跟除 '
和 \
以外的零个或多个字符,然后是 '
|
- 或
(:\w+)
- 第 1 组(这是我们需要获取的值,其余仅用于处理必须忽略匹配的一些文本):一个冒号和一个或多个单词字符。
我正在尝试在 Javasacript 中提取 JPA 命名参数。这是我能想到的算法
const notStrRegex = /(?<![\S"'])([^"'\s]+)(?![\S"'])/gm
const namedParamCharsRegex = /[a-zA-Z0-9_]/;
/**
* @returns array of named parameters which,
* 1. always begins with :
* 2. the remaining characters is guranteed to be following {@link namedParamCharsRegex}
*
* @example
* 1. "select * from a where id = :myId3;" -> [':myId3']
* 2. "to_timestamp_tz(:FROM_DATE, 'YYYY-MM-DD\"T\"HH24:MI:SS')" -> [':FROM_DATE']
* 3. "TO_CHAR(ep.CHANGEDT,'yyyy=mm-dd hh24:mi:ss')" -> []
*/
export function extractNamedParam(query: string): string[] {
return (query.match(notStrRegex) ?? [])
.filter((word) => word.includes(':'))
.map((splittedWord) => splittedWord.substring(splittedWord.indexOf(':')))
.filter((splittedWord) => splittedWord.length > 1) // ignore ":"
.map((word) => {
// i starts from 1 because word[0] is :
for (let i = 1; i < word.length; i++) {
const isAlphaNum = namedParamCharsRegex.test(word[i]);
if (!isAlphaNum) return word.substring(0, i);
}
return word;
});
}
我的灵感来自于 过滤掉包含在 single/double 个引号中的所有字符。
虽然上面的代码完成了上面的 3 个用例。 但是当用户输入
const testStr = '"user input invalid string \' :shouldIgnoreThisNamedParam \' in a string"'
extractNamedParam(testStr) // should return [] but it returns [":shouldIgnoreThisNamedParam"] instead
我确实访问了 hibernate 的源代码,看看那里是如何提取命名参数的,但我找不到执行这项工作的算法。请帮忙。
你可以使用
/"[^\"]*(?:\[\w\W][^\"]*)*"|'[^\']*(?:\[\w\W][^\']*)*'|(:\w+)/g
仅获取第 1 组值。参见regex demo。正则表达式匹配 single/double 引号之间的字符串并捕获 :
+ 所有其他上下文中的一个或多个单词字符。
查看 JavaScript 演示:
const re = /"[^\"]*(?:\[\w\W][^\"]*)*"|'[^\']*(?:\[\w\W][^\']*)*'|(:\w+)/g;
const text = "to_timestamp_tz(:FROM_DATE, 'YYYY-MM-DD\"T\"HH24:MI:SS')";
let matches=[], m;
while (m=re.exec(text)) {
if (m[1]) {
matches.push(m[1]);
}
}
console.log(matches);
详情:
"[^\"]*(?:\[\w\W][^\"]*)*"
-"
,然后"
和\
([^"\]*
) 以外的零个或多个字符,然后是零个或多个重复任何转义字符 (\[\w\W]
) 后跟除"
和\
以外的零个或多个字符,然后是"
|
- 或'[^\']*(?:\[\w\W][^\']*)*'
-'
,然后'
和\
([^'\]*
) 以外的零个或多个字符,然后是零个或多个重复任何转义字符 (\[\w\W]
) 后跟除'
和\
以外的零个或多个字符,然后是'
|
- 或(:\w+)
- 第 1 组(这是我们需要获取的值,其余仅用于处理必须忽略匹配的一些文本):一个冒号和一个或多个单词字符。