Velocity Template - regular expressions - regex

I just started using velocity for a new job and I really don't like what I have found already. At this point, i would actually prefer freemarker =X.
Anyways, i'm trying to do a regular expression and i saw this little bit (search "regular expression"), but that isn't quite the implementation I am doing.
I do not have any access to the java so that option of writing something custom to do this stuff is not there (i'm not even sure if that is possible).
This is what i have right now:
#set ( $envCheck = "(localhost|staging|qa|cms)\\.site" )
#set ( $envCheck = $envCheck.matches($gatewayURL) )
but $envCheck always just comes out as "false". $gatewayURL is defined on the page as well, so that is not the issue.
is this even possible? i was reading that any regexp method that the java String class has is available in the velocity template.

Assuming your $gatewayURL is somethign like this:
#set ( $gatewayURL = "localhost.site" )
Then:
#set ( $envCheck = "(localhost|staging|qa|cms)\.site" )
#set ( $envCheck = $gatewayURL.matches($envCheck) )
No need to mask backslash, and you should be calling matches() on gatewayURL, not regular expression.
Velocity doesn't have its own regexp implementation, it just passes parameters you provide to corresponding native java methods, that's all. So you have pretty much full Java SDK at your disposal.

This answer is way late but probably still good as a reference for Velocity users encountering the same issue.
We use Velocity 1.5 (too big a task to upgrade to 1.7/1.6 as they broke too many templates) and encountered the same issue. The answer above would not work - backlash without escape (\) results in Lexical error and with escape (\\) return false always as I think it is being interpreted literally. The right way to solve it is by using single quote instead of double quotes when defining the regex expression so Velocity would not attempt to interpret the string that is meant for Java.
#set ( $envCheck = '(localhost|staging|qa|cms)\.site' )
#set ( $envCheck = $envCheck.matches($gatewayURL) )

Related

Use of paratheses symbols in django-viewflow flow

I have been at a loss understanding the use of parentheses in django-viewflow flow code.
For example in the code below
start = (
flow.Start(views.StartView)
.Permission('shipment.can_start_request')
.Next(this.split_clerk_warehouse)
)
# clerk
split_clerk_warehouse = (
flow.Split()
.Next(this.shipment_type)
.Next(this.package_goods)
)
from here
It seems as though, a tuple containing functions is assigned to start and to split_clerk_warehouse e.t.c. What does it mean. From my best guess it would seem that the .Next functions accept a tuple as input.
NOTE I do understand the method chaining used here. I am just at a loss to understand the use of braces.
Thanks.
If I understand correctly, you wonder what the use is of the outer brackets.
Let us first write the (first, but applicable to the second) statement without outer brackets:
start = flow.Start(views.StartView).Permission('shipment.can_start_request').Next(this.split_clerk_warehouse)
This is exactly equivalent to code in your sample. But you probably agree that this is quite unreadable. It requires a user to scroll over the code, and furthermore it is a long chain of characters, without any structure. A programmer would have a hard time understanding it, especially if - later - we would also use brackets inside the parameters of calls.
So perhaps it would make sense to write it like:
start = flow.Start(views.StartView).
Permission('shipment.can_start_request').
Next(this.split_clerk_warehouse)
But this will not work: Python is a language that uses spacing as a way to attach semantics on code. As a result it will break: Python will try to parse the separate linkes as separate statements. But then what to do with the tailing dot? As a result the parser would error.
Now Python has some ways to write statements in a multi-line fashion. For example with backslashes:
start = flow.Start(views.StartView). \
Permission('shipment.can_start_request'). \
Next(this.split_clerk_warehouse)
with the backslash we specify that the next line actually belongs to the current one, and thus it is parsed like we wrote this all on a single line.
The disadvantage is that we easily can forget a backslash here, and this would again let the parser error. Furthermore this requires linear work: for every line we have to add one element.
But programming languages actually typically have a feature that programmers constantly use to group (sub)expressions together: brackets. We use it to give precedence (for example 3 * (2 + 5)), but we can use it to simply group one expression over multiple lines as well, like:
start = (
flow.Start(views.StartView)
.Permission('shipment.can_start_request')
.Next(this.split_clerk_warehouse)
)
Everything that is within the brackets belongs to the same expression, so Python will ignore the new lines.
Note that tuple literals also use brackets. For example:
() # empty tuple
(1, ) # singleton tuple (one element)
(1, 'a', 2, 5) # 4-tuple
But here we need to write a comma at the end for a singleton tuple, or multiple elements separated by comma's , (except for the empty tuple).

How to replace characters in string Erlang?

I have this piece of code that gets sessionid, make it a string, and then create a set with key as e.g. {{1401,873063,143916},<0.16443.0>} in redis. I'm trying replace { characters in this session with letter "a".
OldSessionID= io_lib:format("~p",[OldSession#session.sid]),
StringForOldSessionID = lists:flatten(OldSessionID),
ejabberd_redis:cmd([["SADD", StringForSessionID, StringForUserInfo]]);
I've tried this:
re:replace(N,"{","a",[global,{return,list}]).
Is this a good way of doing this? I read that regexp in Erlang is not a advised way of doing things.
Your solution works, and if you are comfortable with it, you should keep it.
On my side I prefer list comprehension : [case X of ${ -> $a; _ -> X end || X <- StringForOldSessionID ]. (just because I don't have to check the function documentation :o)
re:replace(N,"{","a",[global,{return,list}]).
Is this a good way of doing this? I read that regexp in Erlang is not
a advised way of doing things.
According to official documentation:
2.5 Myth: Strings are slow
Actually, string handling could be slow if done improperly. In Erlang, you'll have to think a little more about how the strings are used and choose an appropriate representation and use the re module instead of the obsolete regexp module if you are going to use regular expressions.
So, either you use re for strings, or:
leave { behind(using pattern matching)
if, say, N is {{1401,873063,143916},<0.16443.0>}, then
{{A,B,C},Pid} = N
And then format A,B,C,Pid into string.
Since Erlang OTP 20.0 you can use string:replace/3 function from string module.
string:replace/3 - replaces SearchPattern in String with Replacement. 3rd function parameter indicates whether the leading, the trailing or all encounters of SearchPattern are to be replaced.
string:replace(Input, "{", "a", all).

Find/Replace string that doesn't contain quotes

I have inherited a rather large/ugly php codebase (language is unimportant, this is a generic vim question) , where nothing is quoted properly (old php doesn't mind, but new php versions throw warnings).
I'd like to turn $something[somekey] into $something['somekey'], only if its not already quoted or contain the character $
I was trying to build a regular expression to quote the keys, but just cant seem to be able get it to cooperate.
This is what i have so far, which doesn't work but maybe will help explain my question better. And to show that i have actually tried.
:%s/\v\$(.{-})\[(['"$]#<!.{-})\]/$\1['\2']/
My goal is to have something like this:
$something[somekey] = $something['somekey']
$somethingelse[someotherthing] = $something['someotherthing']
$another['key'] = $another['key'] (is ignored)
$yetanother["keykey"] = $yetanother["keykey"] (is ignored)
$derp[$herp] = $derp[$herp] (is ignored)
$array[3] = $array[3] (is ignored)
These can appear anywhere in text, even multiple on the same line, and even touching each other like $something[key]$something[key2], which i would like to be replaced with $something['key']$something['key2']
Another problem, there seems to be random javascript arrays in some files.. which have [] square brackets. So the regex needs to check to see if it starts with $ and text before the brackets.
Im probably asking for the impossible, but any help on this would be great before i go insane editing each file one by one manually.
EDIT: forgot that keys can be numeric, and shouldn't be quoted.
I tried the following, which processed everything from your question correctly:
:%s/\[\(\I\i*\)\]/['\1']/g
Or, with optional white spaces inside the parens:
:%s/\[\s*\(\I\i*\)\s*\]/['\1']/g
And also checking for $identifier before the parens:
:%s/\(\$\i\+\)\[\s*\(\I\i*\)\s*\]/\1['\2']/g

How can I create a qr// in Perl 5.12 from C?

This has been working for me in 5.8 and 5.10, but in 5.12 my code creates this weird non-qr object:
# running "print Dumper($regex)"
$VAR1 = bless( do{\(my $o = '')}, 'Regexp' );
Whereas printing a qr// not created by my code looks like this:
# running "print Dumper(qr/foo/i)"
$VAR1 = qr/(?i-xsm:foo)/;
My code is basically:
REGEXP *rx = re_compile(pattern, flags);
SV *regex = sv_2mortal(newSVpv("",0));
sv_magic(regex, (SV*)rx, PERL_MAGIC_qr, 0, 0);
stash = gv_stashpv("Regexp", 0);
sv_bless(newRV((SV*)regex), stash);
Anyone know how to correctly create a regex from a string in 5.12?
Thanks for putting me on the right track, guys, it turns out I was seriously overthinking this. They just cut out the magic line and don't create the PV.
This is all you need to do in Perl 5.12:
REGEXP *rx = re_compile(pattern, flags);
SV *regex = newRV((SV*)rx);
stash = gv_stashpv("Regexp", 0);
sv_bless(regex, stash);
Take a look at the comments in this answer by hobbs. I've copied it below for ease of reading:
Regex objects actually get slightly more "core" in 5.12.0, as they're now references to scalars of type REGEXP rather than references to scalars with magic. This is, however, completely invisible to user code, unless you manage to bypass overloaded stringification, in which case you'll notice that regexes now print as Regexp=REGEXP(0x1234567) instead of Regexp=SCALAR(0x1234567)
I'm not especially familiar with XS, but I suspect you can't use a scalar value any more to create your regex.
Perl 5.12 changed regexps to be first class objects, which you find as part of the tangential discussion in How do I check if a scalar has a compiled regex it in?.
I'm not an XS person, so I don't know what you need to change in your code to make it work out. Searching for 'REGEXP' in the perl sources shows the fixes they made to the core modules to use the new stuff.

Regular Expression - how to find text within particular if blocks?

I'm new to regular expressions and would like to use one to search through our source control to find text within a block of code that follows a particular enum value. I.e.:
/(\/{2}\#debug)(.|\s)*?(\/{2}\#end-debug).*/
var junk = dontWantThis if (junk) {dont want this} if ( **myEnumValue** ) **{ var yes = iWantToFindThis if (true) { var yes2 = iWantThisToo } }**
var junk2 = dontWantThis if (junk) {dont want this}
var stuff = dontWantThis if (junk) {dont want this} if ( enumValue ) { wantToFindThis }
var stuff = iDontWantThis if (junk) {iDontWantThisEither}
I know I can use (\{(/?[^\>]+)\}) to find if blocks, but I only want the first encompassing block of code that follows the enum value I'm looking for. I've also notice that using (\{(/?[^\>]+)\}) gives me the first { and last }, it doesn't group the subsequent {}.
Thank you!
Tim
Regexps simply can't handle this kind of stuff. For this you'll need a parser and scanner.
As others hint at, it's mathematically impossible to do with with regular expressions (at least in general; you might be able to get it to work if you have highly specialized cases). Try using a combination of lex and awk to get the desired results if you want to stick with standard Unix tools, or just go to Perl, Python, Ruby, etc. and build up the lexical parsing you need.
While nesting is a problem, you could use backtracking and lookahead to effectively count your matching braces or quotes. This is not strictly part of a regular expression but has been added to many regex libraries, such as the one in .NET, perl, and java; probably more. I wouldn't recommend that you go this route, as you should find it easier to lexically parse this. But if you do try this as a quick fix, absolutely collect a few test cases and run them through regexbuddy or expresso.