Velocity正则表达式实现大小写不敏感匹配

5

我想在一个 Velocity模板 中(使用JavaScript)实现类似词汇表的功能。以下是用例:

  • 有大量物品,它们的描述可能包含对预定义术语的引用
  • 有一份已定义的术语清单 -> allGlossary
  • 我希望自动查找并标记出所有在我的物品描述中出现过的allGlossary列表中的项目

示例:

allGlossary = ["GUI","RBG","fine","Color Range"]

物品描述: The interface (GUI) shall be generated using only a pre-defined RGB color range.

运行脚本后,我希望描述看起来像这样: "The interface (GUI) shall be generated using only a pre-defined RGB Color Range."

注意:即使 "fine" 出现在描述中(defined),也不应该被标记。

我考虑将每个物品的描述拆分为单词,但这样会错过所有具有多个单词的词汇表项。我的当前想法是在每个描述中查找列表中的每个项目,但我有以下限制:

  • 我需要精确匹配两个列表中的项目(单个和多个单词)
  • 搜索不区分大小写
  • 找到的项目可能位于文本开头或结尾,并由各种符号分隔:空格、逗号、句号、括号、方括号等

我有以下代码,它可以工作但不区分大小写:

#set($desc = $item.description)
#foreach($g in $allGlossary)
    #set($desc = $desc.replaceAll("\b$g\b", "*$g*"))
#end##foreach

能有人帮忙将这个不区分大小写吗?或者有更好的方法吗?

谢谢!

更新: 根据下面的答案,我试图在我的Velocity模板页面中执行以下操作:

#set($allGlossary = ["GUI","RGB","fine","Color Range"])
#set($itemDescription = "The interface (GUI) shall be generated using only a pre-defined RGB color range.")

<script type="text/javascript">
    var allGlossary = new Array();
    var itemDescription = "$itemDescription";
</script>

#foreach($a in $allGlossary)
    <script type="text/javascript">
        allGlossary.push("$a");
        console.log(allGlossary);
    </script>
#end##foreach

<script type="text/javascript">
    console.log(allGlossary[0]);
</script>

问题在于,如果我尝试显示整个 allGlossary 数组,它包含正确的元素。但是一旦我尝试仅显示其中一个(如示例中所示),就会出现错误Uncaught SyntaxError: missing ) after argument list

最有可能这不是一个你想要使用正则表达式来解决的问题。 - maraaaaaaaa
好的,我愿意听取任何其他建议。 - Mircea M
1个回答

4

您提到您正在使用JavaScript进行这些计算。因此,一个简单的方法是遍历您的allGlossary数组,并为每个迭代创建一个正则表达式,并使用这个表达式在文本中查找和替换所有出现。

要仅查找介于单词边界之间的值,可以使用\b。这允许匹配像(RGB)Color Range?这样的匹配项。要匹配不区分大小写,可以使用/i标志,要在字符串中查找每个实例(而不仅仅是第一个实例),可以使用全局标志/g

如果您在正则表达式中使用变量,则只有在使用正则表达式的构造函数表示法时才支持动态创建正则表达式(不要忘记转义斜杠)。对于静态正则表达式,您也可以使用:/\bRGB\b/ig。这是动态的内容:

new RegExp("\\b("+item+")\\b", 'gi');

这是一个基于你的示例字符串的完全功能性示例。 它用HTML包装的版本替换了allGlossary数组的每个项目。

var allGlossary = ["GUI","RGB","fine","Color Range"]
var itemDescription = "The interface (GUI) shall be generated using only a pre-defined RGB color range.";

for(var i=0; i<allGlossary.length; i++) {
  var item = allGlossary[i];
  var regex = new RegExp("\\b("+item+")\\b", 'gi');
  itemDescription = itemDescription.replace(regex, "<b>$1</b>");
}

console.log(itemDescription);

如果这不是您期望的解决方案,您可以在下面留言。

嗨,谢谢你的代码,它按预期工作,但不幸的是无法在Velocity模板中使用。在纯JavaScript中有多种方法可以实现,但Velocity不允许这样做。我尝试将代码单独放在<script>...</script>块中,但它不起作用。我还尝试仅使用我拥有的代码中的静态RegEx,但它也没有起作用(停止查找任何内容)。我将继续尝试使用Velocity和Javascript的组合来实现我的目标,但似乎存在我尚未完全了解的限制... - Mircea M
你能在Velocity模板中使用'\b('+item+')\b'进行测试吗?同时,将"转换为',将\\更改为\\。@MirceaM - MohaMad
很抱歉,执行该脚本似乎不起作用。Velocity似乎不将<script type="text/javascript">...</script>之间的代码视为实际代码,并将[...]解释为链接。这反过来会引发语法错误(意外的令牌<),因为呈现的代码实际上是"var allGlossary = <a onclick="return checkDisca..."。我尝试转义[和],但出于某种原因它不起作用。尝试了[、\[、\[-都没有成功。这让我想起了我对原帖的更新,在那里我以不同的方式分配数组的值,但也遇到了问题。 - Mircea M
好的,找到了一种方法来排除 [..] 的解释。有了这个,上面的例子也可以工作了。现在将尝试重新实现我的页面,使用混合了 JavaScript 和 Velocity 的方式。 - Mircea M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接