Escaping dollars groovy
Asked Answered
C

2

5

I'm having trouble escaping double dollars from a string to be used with regex functions pattern/matcher.

This is part of the String:

WHERE oid_2 = $$test$$ || oid_2 = $$test2$$

and this is the closest code I've tried to get near the solution:

List<String> strList = new ArrayList<String>();
Pattern pattern = Pattern.compile("\$\$.*?\$\$");
log.debug("PATTERN: "+pattern)
Matcher matcher = pattern.matcher(queryText);
while (matcher.find()) {
    strList.add(matcher.group());
}
log.debug(strList)

This is the debug output i get

- PATTERN: $$.*?$$
- []

So the pattern is actually right, but the placeholders are not found in the string.

As a test I've tried to replace "$$test$$" with "XXtestXX" and everything works perfectly. What am I missing? I've tried "/$" strings, "\\" but still have no solution.

Countrified answered 12/4, 2017 at 7:49 Comment(5)
See ideone.com/Olm30xDisrupt
"\\$\\$.*?\\$\\$" says: illegal string body character after dollar sign; solution: either escape a literal dollar sign "\$5" or bracket the value expression "${5}" @ line 7, column 38. Pattern pattern = Pattern.compile("\\$\\$.*?\\$\\$") ^ 1 errorCountrified
While using Slashy string it works! Thanks a lot, I was sure I had tried that solution but somehow I didn't, thanks again!Countrified
Ok, you need to escape the dollar in a double quoted string literal first, else interpolation will be attempted.Disrupt
I was missing the fact that I had to escape dollars in slashy strings too, I think that was the problem. Many thanks Wiktor!Countrified
B
6

Note that a $ in regex matches the end of the string. To use it as a literal $ symbol, you need to escape it with a literal backslash.

You used "\$\$.*?\$\$" that got translated into a literal string like $$.*?$$ that matches 2 end of string positions, any 0+ chars as few as possible and then again 2 end of strings, which has little sense. You actually would need a backslash to first escape the $ that is used in Groovy to inject variables into a double quoted string literal, and then use 2 backslashes to define a literal backslash - "\\\$\\\$.*?\\\$\\\$".

However, when you work with regex, slashy strings are quite helpful since all you need to escape a special char is a single backslash.

Here is a sample code extracting all matches from the string you have in Groovy:

def regex = /\$\$.*?\$\$/;
def s = 'WHERE oid_2 = $$test$$ || oid_2 = $$test2$$'
def m = s =~ regex
(0..<m.count).each { print m[it] + '\n' }

See the online demo.

Bettiebettina answered 12/4, 2017 at 8:6 Comment(5)
What if I had a variable for each placeholder with the same name, how would I replace the values in it? For example, I have String test="1" and String test2="2", what's the easiest way to have all $$test$$ replaced with "1" and all $$test2$$ replaced with "2"? I hope the requirement it's clearCountrified
Do you mean you need to replace the variables (by names) with their values? Not something like this?Disrupt
If you have them inside a string, then use something like this.Disrupt
The idea is that i have lots of queries i can't edit, and those have $$placeholders$$, I have every placeholder as input in my script and it has the same name as the $$placeholder$$. EG: input variables are: test, test1, test2. My query contains $$test$$ $$test1$$, another query may contain $$test1$$ $$test1$$ $$test2$$ etcCountrified
Done, absolutely helpful!Countrified
M
3

Anyone who gets here might like to know another answer to this, if you want to use Groovy slashy strings:

myComparisonString ==~ /.*something costs [$]stuff.*/

I couldn't find another way of putting a $ in a slashy string, at least if the $ is to be followed by text. If, conversely, it is followed by a number (or presumably any non-letter), this will work:

myComparisonString ==~ /.*something costs \$100.*/

... the trouble being, of course, that the GString "compiler" (if that's its name) would recognise "$stuff" as an interpolated variable.

Myrilla answered 18/4, 2018 at 17:4 Comment(1)
Non obvious to me. Tx for thisCuriosa

© 2022 - 2024 — McMap. All rights reserved.