Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Velocity RegEx for case insensitive match

Tags:

I want to implement a sort of Glossary in a Velocity template (using Javascript). The following is the use case:

  • there are a large number of items whose description may contain references to predefined terms
  • there is a list of terms which are defined -> allGlossary
  • I want to automatically find and mark all items in the allGlossary list that appear in the description of all my items

Example:

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

Item Description: The interface (GUI) shall be generated using only a pre-defined RGB color range.

After running the script, I would expect the Description to look like this: "The interface (GUI) shall be generated using only a pre-defined RGB Color Range."

NOTE: even though "fine" does appear in the Description (defined), it shall not be marked.

I thought of splitting the description of each item into words but then I miss all the glossary items which have more than 1 word. My current idea is to look for each item in the list in each of the descriptions but I have the following limitations:

  • I need to find only matches for the exact items in the 2 lists (single and multiple words)
  • The search has to be case insensitive
  • Items found may be at the beginning or end of the text and separated by various symbols: space, comma, period, parentheses, brackets, etc.

I have the following code which works but is not case-insensitive:

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

Can someone please help with making this case-insensitive? Or does anyone have a better way to do this?

Thanks!

UPDATE: based on the answer below, I tried to do the following in my Velocity Template page:

#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>

The issue is that if I try to display the whole allGlossary Array, it contains the correct elements. As soon as I try to display just one of them (as in the example), I get the error Uncaught SyntaxError: missing ) after argument list.

like image 657
Mircea M Avatar asked Feb 13 '17 21:02

Mircea M


1 Answers

You mentioned, that you are using JavaScript for these calculations. So one simple way would be to just iterate over your allGlossary array and create a regular expression for each iteration and use this expression to find and replace all occurrences in the text.

To find only values which are between word boundaries, you can use \b. This allows matches like (RGB) or Color Range?. To match case insensitive, you can use the /i flag and to find every instance in a string (not just the first one), you can use the global flag /g.

Dynamic creation of regular expressions (with variables in it) is only supported in JavaScript, if you use the constructor notation of a regular expression (don't forget to escape slashes). For static regular expressions, you could also use: /\bRGB\b/ig. Here is the dynamic one:

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

Here is a fully functional example based on your sample string. It replaces every item of the allGlossary array with a HTML wrapped version of it.

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);

If this is not your expected solution, you can leave a comment below.

like image 95
ssc-hrep3 Avatar answered Nov 15 '22 05:11

ssc-hrep3