【问题标题】:Extract JPA Named Parameters in Javascript在 Javascript 中提取 JPA 命名参数
【发布时间】:2021-10-20 20:37:39
【问题描述】:

我正在尝试在 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;
    });
}

我受到了解决方案的启发 https://stackoverflow.com/a/11324894/12924700 过滤掉所有用单引号/双引号括起来的字符。

虽然上面的代码满足了上面的 3 个用例。 但是当用户输入

const testStr  = '"user input invalid string \' :shouldIgnoreThisNamedParam \' in a string"'
extractNamedParam(testStr) // should return [] but it returns [":shouldIgnoreThisNamedParam"] instead

我确实访问了 hibernate 的源代码以查看命名参数是如何在那里提取的,但我找不到正在工作的算法。请帮忙。

【问题讨论】:

    标签: javascript regex hibernate named-parameters string-algorithm


    【解决方案1】:

    你可以使用

    /"[^\\"]*(?:\\[\w\W][^\\"]*)*"|'[^\\']*(?:\\[\w\W][^\\']*)*'|(:\w+)/g
    

    仅获取第 1 组值。请参阅regex demo。正则表达式匹配单引号/双引号之间的字符串,并在所有其他上下文中捕获 : + 一个或多个单词字符。

    查看 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 组(这是我们需要获取的值,其余的只是用于消耗一些必须忽略匹配的文本):一个冒号和一个或多个单词字符。

    【讨论】:

    • 感谢您的回答。它就像一个魅力。但是,我想了解这个正则表达式是如何工作的。在 regex101mdn 中的解释的帮助下,我设法理解这里有 3 种替代方案,我们只对带括号的子字符串匹配感兴趣。你能解释一下alternative1/alternative2 regex是如何工作的吗?即"[^\\"]*(?:\\[\w\W][^\\"]*)*"
    猜你喜欢
    • 2012-11-03
    • 2014-09-03
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 2019-05-29
    • 2022-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多