2

i need your help. in vbscript i have a string such as

s = 'Abc' and 'Def' Or 'Ghin' In 'jkl' not 'mnoR' And ... or ... NOT ... iN ...

and i want to uppercase these specific 4 operators (in any combination of lower and upper text): and, or, in, not, to Uppercase.

These operators exist outside the quotes (') - because between them i have business rules. This is important, because, as you can see in 3rd rule ('Ghin') i have 'in' in the name of the rule and in these cases i do not want the text between the quotes (business rule name) to be altered.

How can i solve this in vbscript, preferently using RegEx?

TIA

EDIT: Thanks for your help.

Sorry, but i forgot to mention one detail: i can have text outside the quotes, namely "(" , ")", "[","]" or conditions as "1 = 1", but again: the operators to be changed exist outside the quotes and inside quotes nothing is done.

Using the previous example: s = "('abc' and ['Def' Or 'Ghin'] In 'jkl' not 1=1 AND 'mnoR' And 'pqr' or 'xyz' NOT 'lmn' iN 'Opq')"

s = "('abc' AND ['Def' OR 'Ghin'] IN 'jkl' NOT 1=1 AND 'mnoR' AND 'pqr' OR 'xyz' NOT 'lmn' IN 'Opq')"

lrmmf
  • 63
  • 7

5 Answers5

4

In other languages you may use a fancy look around pattern to (logically) apply a regexp to parts of your input only, in VBScript you should use either a regexp replace function with a state or Split().

Demo script for the first alternative:

Dim gb_magic : gb_magic = True
Function gf_magic(sMatch, nPos, sSrc)
  gf_magic = sMatch
  If "'" = sMatch Then
     gb_magic = Not gb_magic
  Else
     If gb_magic Then
        gf_magic = UCase(sMatch)
     End If
  End If
End Function

  Dim s : s = "s = 'Abc and def' and 'not Def' Or 'Ghin' In 'jkl in or' not 'mnoR'"
  WScript.Echo s
  Dim r : Set r = New RegExp
  r.Global     = True
  r.IgnoreCase = True
  r.Pattern    = "and|not|or|in|'"
  gb_magic     = True
  s = r.Replace(s, GetRef("gf_magic"))
  WScript.Echo s

output:

s = 'Abc and def' and 'not Def' Or 'Ghin' In 'jkl in or' not 'mnoR'
s = 'Abc and def' AND 'not Def' OR 'Ghin' IN 'jkl in or' NOT 'mnoR'
Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
  • Nice solution, but I still dislike your variable naming :). Does it stands for g(lobal)b(oolean)_magic / g(lobal)f(unctionpointer)_magic? – AutomatedChaos Mar 18 '14 at 11:11
  • @AutomatedChaos - by correctly decoding my naming scheme, you proved its worth. In earnest: the names should connotate "something special ahead" and "sorry, but must be global in VBScript", the "magic" part should be improved wrt the real world context. Feel free to edit the demo code using the names you like better. – Ekkehard.Horner Mar 18 '14 at 13:34
  • @Ekkehard.Horner I know and it is no problem at all (it is understandable for the outsider as you said). Even better: When I read a post, I can tell if it is from you even if I haven't seen the name. See it as your signature. – AutomatedChaos Mar 18 '14 at 20:38
  • Great method! I found that in common case the arguments passing to the function are: `(strMatch, strSubMatch1[, strSubMatch2[, strSubMatch3 ... ]], lngPos, strSource)` - so the number of the arguments depends on the number of submatches which set with "(pattern)". – omegastripes Apr 09 '14 at 22:00
2

Keeping the method exposed by Ekkehard solution, but translating the state variable into the regular expression.

It has the drawback of a string concatenation inside the function, but it only gets called for the found operators and not for the quotes.

Dim originalString    
    originalString = "not 'Abc and def' and 'not Def' Or 'Ghin' In 'jkl in or' not 'mnoR' and"

Dim convertedString

    Function correctCase(matchString,leftPart,operator,rightPart,position,sourceString)
        correctCase = leftPart & UCase(operator) & rightPart
    End Function 

    With New RegExp
        .Pattern = "((?:'[^']*'){0,}\s*)(and|or|not|in)((?:\s*'[^']*'){0,})"
        .Global = True 
        .IgnoreCase = True
        convertedString = .Replace(originalString,GetRef("correctCase"))
    End With 

    WScript.Echo originalString
    WScript.Echo convertedString
MC ND
  • 69,615
  • 8
  • 84
  • 126
  • This is just as beautiful as it is elegant. Now I'm waiting for the OP to tell us _Oh, and by the way, quotes between quotes are escaped by a backslash. Give me the codez plz!?_. – AutomatedChaos Mar 18 '14 at 11:07
1

Using regular expressions is a must?

s = "('abc' and ['Def' Or 'Ghin'] In 'jkl' not 1=1 AND 'mnoR' And 'pqr' or 'xyz' NOT 'lmn' iN 'Opq')"
p = split(s, "'")
for i = 0 to ubound(p) step 2
    p(i) = ucase(p(i))
next
r = join(p, "'")
msgbox r
omegastripes
  • 12,351
  • 4
  • 45
  • 96
0

Something like this should work

Dim s

s = "'abc' and 'Def' Or 'Ghin' In 'jkl' not 'mnoR' And 'pqr' or 'xyz' NOT 'lmn' iN 'asd'"

s = RegExReplace(s,"\band\b","AND")
s = RegExReplace(s,"\bor\b","OR")
s = RegExReplace(s,"\bnot\b","NOT")
s = RegExReplace(s,"\bin\b","IN")
msgbox s

Function RegExReplace(OriginalStr, RegExPattern, NewStr)
    Set objRegEx = CreateObject("VBScript.RegExp")
    objRegEx.Global = True   
    objRegEx.IgnoreCase = True
    objRegEx.Pattern = RegExPattern
    RegExReplace=objRegEx.Replace(OriginalStr, NewStr)
End Function
Pankaj Jaju
  • 5,371
  • 2
  • 25
  • 41
  • Hi, this works great, the only disadvantage is having to create 2 functions - one "main" that calls the 4 RegExReplaces. Thanks – lrmmf Mar 19 '14 at 12:51
  • Thanks and having a separate function allows code reusablity. But I would recommend @Ekkehard.Horner way of doing it. That's quite clever. – Pankaj Jaju Mar 19 '14 at 13:00
0

I would agree a regex solution is the way to go. But it seems to me that you could just search for your keywords surrounded by spaces, unless of course your business rules include that type of pattern as well.

For Each k In Array(" AND ", " OR ", " IN ", " NOT ")
    s = Replace(s, k, k, 1, -1, vbTextCompare)
Next

This will find your keywords (on their own, not contained within another word) and replace any instances with uppercase versions.

Bond
  • 16,071
  • 6
  • 30
  • 53