Piece or String function using Matches [A-Z]
I am trying to match on config items that have the same Vendor name in them for custom alerting.
Example:
FromVendornameSiteADT
ToVendornameORM
Where Vendorname could be several systems that have multiple interfaces.
How can I find all config items (interface names) with the same Vendor name, without explicitly naming them?
I was trying to use $Piece to segment out the CamelCase pieces (as the name I want is always the 2nd Capitalized section), but could not find a way to integrate match regex logic (e.g. [A-Z]) inside $Piece or other String extract functions.
Comments
Hello Brian,
I'm not sure what your other code for this alerting looks like, but would the Ensemble Utility Function "Contains" be useful?
TEST>w ##class(Ens.Util.FunctionSet).Contains("FromVendornameSiteADT","Vendor"))
1
There are also utility functions to convert a string to all upper/lowercase, if you need that also.
Unfortunately, Vendorname is just a placeholder for the section of the String I need to extract. I'm trying to find a way to pull that section (i.e. the 2nd Capitalized word) from the string without naming it.
i.e.:
FromEpicADT > "Epic"
ToHealthshareNorthADT > "Healthshare"
Interface Maps includes a config item search function that can search on partial name matches:
https://docs.intersystems.com/healthconnect20201/csp/docbook/DocBook.UI… Interface Maps
I think this has the same problem I describe in my reply above.
Hi Brian,
Could you please with below code.
----------------------------------------------------
Class Sample.TempUtil Extends %RegisteredObject
{
ClassMethod GetSecondUpperCase(pInput As %String) As %String
{
;w ##class(Sample.TempUtil).GetSecondUpperCase("GetSecondUpperCase")
SET stsrtpos=$LOCATE(pInput,"[[:upper:]]{1}",2)
SET endpos=$LOCATE(pInput,"[[:upper:]]{1}",(stsrtpos+1))
SET result=$EXTRACT(pInput,stsrtpos,(endpos-1))
quit result
}
}
----------------------------------------------------------------
Regards,
Muni Ganesh
Thanks! I was almost there... I think this will work nicely!
Have a look at %Regex.Matcher. Since you always want the 2nd capitalized section you can just make that your regex capture group:
set matcher=##class(%Regex.Matcher).%New("^[A-Z][a-z]*([A-Z][a-z]*)")
set matcher.Text="ToVendornameORM"
if matcher.Locate() {
write "Found ",matcher.Group(1)," at position ",matcher.Start,!
}This gives me the output:
Found Vendorname at position 1
Thanks! I think this would have gotten me there too!
Here's the code to get capitalized piece of string by number:
/// Get Capitalized piece.
/// str - string to search
/// piece - 1-based piece to return
/// write ##class(test.CustomQuery).GetCapitalizedPiece()
ClassMethod GetCapitalizedPiece(str As %String = "lowerHelloWorldAgainHelloWorldAgainHelloWorldAgainHelloWorldAgain", piece As %Integer = 1) As %String
{
// Only uppercase letters
set upper = $tr(str, $zcvt(str, "l"))
// Number of uppercase letteres
set capCount = $l(upper)
// Quit if requested piece can not exist
quit:piece>capCount ""
quit:piece<1 ""
// First letter in our capitalized piece
set startLetter = $e(upper, piece)
// All previous capitalized letters
set prevLetters = $e(upper, 1, piece - 1)
// Check if current capitalized letter is a first capitalized letter
// If not - skip previous capitalized letters
if '$find(prevLetters, startLetter) {
set start = $find(str, startLetter) - 1
} else {
set count = $l(prevLetters, startLetter) + 1
set start = 0
while $i(count,-1) {
set start = $find(str, startLetter, start)
}
set start = start - 1
}
// Is this capitalized piece the last one?
if piece=capCount {
set end = $l(str)
} else {
set end = $find(str, $e(upper, piece + 1), start) - 2
}
quit $e(str, start, end)
}Advantages over regexp:
- ~50 times faster
- Get any piece, not only the second one (although generating required regexp by piece number seems easy to do)