Question
· Aug 12, 2022

Efficient regular expression to detect 3 attributes in URL

Hello community,

First of all thanks for your time reading and answering this post:

We have read the following topics:

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

https://community.intersystems.com/post/using-regular-expressions-cach%C...

https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic....

https://community.intersystems.com/post/string-manipulation

https://community.intersystems.com/post/string-manipulation

 

We have the following need:

There is an URL which has 3 parameters:

[URL REST]/ServiceRequest?[EXTERNAL HEALTH CENTER CODE]:authoredOn=ge[START DATE RANGE (GREATER THAN OR EQUAL TO)]:authoredOn=le[END DATE RANGE (LESS THAN OR EQUAL TO)]

A real example is:

http://IP:19XXX/ServiceRequest?1111111111:authoredOn=ge2022-01-10:authoredOn=le2022-01-13
 

However, the health centers may interchange the order of the date attributes:

[URL REST]/ServiceRequest?[EXTERNAL HEALTH CENTER CODE]:authoredOn=le[END DATE RANGE (LESS THAN OR EQUAL TO)]:authoredOn=ge[START DATE RANGE (GREATER THAN OR EQUAL TO)]

Being a real example:

http://IP:19XXX/ServiceRequest?1111111111:authoredOn=le2022-01-13:authoredOn=ge2022-01-10
 

 

We have thought about the following rudimentary logic to obtain the 3 attributes:

set externalCenterCode = $PIECE($PIECE(url, :authoredOn=, 1) , /ServiceRequest? , 2)

set startDateRange = $PIECE($PIECE( url, :authoredOn=ge, 2) , :authoredOn=le , 1)

set endDateRange = $PIECE($PIECE( url, :authoredOn=le, 2) , :authoredOn=ge , 1)

 

📌📍 Is there a more readable, understandable, simple and correct way using regular expressions to obtain the 3 attributes?

We would be grateful if you could provide us with documentation, manuals, examples, references, explanations or any other means and/or tool that would allow us to solve this need in the most understandable, legible and correct way possible.

Thank you in advance
Best regards

 

We ask you because you are more experimented, skilled and you have more familiarity with ObjectScript and Ensemble.

In addition we have checked that the previous sentence:

set startDateRange = $PIECE($PIECE( url, ":authoredOn=ge", 2) , ":authoredOn=le", 1)

Would fail when ge is at the ending as in the following url:

set url = "http://IP:19XXX/ServiceRequest?1111111111:authoredOn=le2022-01-13:author..."

 

Plus, it would fail in the next line:

set endDateRange = $PIECE($PIECE( url, ":authoredOn=le", 2) ," :authoredOn=ge" , 1)

When le is at the ending, in the URL:

set url = "http://IP:19XXX/ServiceRequest?1111111111:authoredOn=ge2022-01-10:author..."

 

🔘 Could you help us please?

Thank you in advance
Best regards

$ZV: Cache for UNIX (Red Hat Enterprise Linux for x86-64) 2018.1.6 (Build 717U) Thu Feb 24 2022 13:27:54 EST
Discussion (2)2
Log in or sign up to continue

Say you have this string:

1111111111:authoredOn=ge2022-01-10:authoredOn=le2022-01-13

How do you want to slice it:

authoredOn=ge2022-01-10

authoredOn=le2022-01-13

what's 1111111111 doing there?

Something like this should work:

set str = "1111111111:authoredOn=ge2022-01-10:authoredOn=le2022-01-13"
set str = $lfs(str, ":")
for i=1:1:$ll(str) {
	set param = $lg(str,i)
	if $l(param,"=")=2 {
		set key = $p(param,"=",1)
		set value = $p(param,"=",2)
		set params(key, $i(params(key)))=value
	}
}
zw params
ClassMethod OnPage() As %Status [ ServerOnly = 1 ]
{
    
    //just the query string...
    set qs=%request.CgiEnvs("QUERY_STRING")
        
    //SOLUTION 1: $piece only
    set externalCenterCode=$p(qs,":")	
    set startDateRange=$p($p(qs,":authoredOn=le",2),":")
    set endDataRange=$p($p(qs,":authoredOn=ge",2),":")

    
    //SOLUTION 2: generic solution if params grow	
    for i=1:1:$l(qs,":") {
        set nvp=$p(qs,":",i),name=$p(nvp,"=",1),value=$p(nvp,"=",2)
        //fix the quirks
        if value="" set value="name",name="ecc"
        if name="authoredOn" set name=$e(value,1,2),value=$e(value,3,*)
        set params(name)=value
    }

    //SOLUTION 3: regex(ish) solution
    set code=$p(qs,":")
    set loc=$locate(qs,"le\d{4}-\d{2}-\d{2}")
    set start=$e(qs,loc+2,loc+11)
    set loc=$locate(qs,"ge\d{4}-\d{2}-\d{2}")
    set end=$e(qs,loc+2,loc+11)


    //some helper code to dump the variables into the CSP page
    write !,"<pre>"
    zwrite
    //use this to take a good look at the request object...
    zwrite %request
    write !,"</pre>"
    quit $$$OK
}

Here are three solutions and a couple of inline tips, including your request for regex example

I wouldn't worry too much about using $piece, its very common to use it in this way

Eduards comment above also has a fourth suggestion to use $lfs (list from string) which is also commonly used as a way of piecing out data