Regular Expressions


REGEXP.WBT  v1.06  20030917

The following WinBatch 'User Defined Functions' make use of the
Visual Basic Scripting Edition OLE object 'VBScript.RegExp'
to support Regular Expressions in WinBatch scripts.


If you have questions about WinBatch, you are encouraged to use online WebBoard BBS at http://webboard.windowware.com


;===============================================================================================================================================
; udflib.RegExp.wbt  v1.06  20030917                                                                                   (c)20020708.Detlev Dalitz
;===============================================================================================================================================
; A regular expression is a pattern of text that consists of ordinary characters
; (for example, letters a through z) and special characters, known as metacharacters.
; The pattern describes one or more strings to match when searching a body of text.
; The regular expression serves as a template for matching a character pattern to the string being searched.
;===============================================================================================================================================
;
;   This WinBatch library file contains two sections of 'user defined functions'
;   to provide regular expression search facilities in WinBatch.
;   -  'high level' routines,
;   -  'low  level' routines.
;
;   The 'high level' routines hide the VB RegExp object.
;   The properties of the RegExp object must be set by udf parameter list.
;   These functions are the worker functions and will fit for RegExp tasks in general.
;
;   The 'low level' routines allow handling of the RegExp object at object interface level.
;   The 'low level' udfs are mostly simple wrappers (with some overhead in relation to 'pure' object use).
;   The 'low level' functions were build mainly for generalizing the RegExp udf interface.
;
;===============================================================================================================================================



;===============================================================================================================================================
; 'High Level' Routines     (VB Regular Expression object encapsulated)
;===============================================================================================================================================
; udfRegExpTest             (sSearchString, sRegExpPattern, bIgnoreCase)
; udfRegExpMatch            (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch, bMultiLine, sMatchPropSep, sMatchItemSep)
; udfRegExpReplace          (sSearchString, sRegExpPattern, sReplaceString, bIgnoreCase, bGlobalSearch)
;-----------------------------------------------------------------------------------------------------------------------------------------------
; udfRegExpGetMatchCount    (sMatchList, sMatchItemSep)
; udfRegExpGetMatch         (iMatch, sMatchList, sMatchItemSep)
;
; udfRegExpGetMatchValue    (sMatchItem, sMatchPropSep)
; udfRegExpGetMatchIndex    (sMatchItem, sMatchPropSep)
; udfRegExpGetMatchLength   (sMatchItem, sMatchPropSep)
;
; udfRegExpGetSubMatchCount (sMatchItem, sMatchPropSep)
; udfRegExpGetSubMatchValue (iSub, sMatchItem, sMatchPropSep)
;
; udfRegExpCheckPattern     (sRegExpPattern)
;===============================================================================================================================================



;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpCheckPattern (sRegExpPattern)
sRegExpPattern = StrReplace(sRegExpPattern,"\(","")
sRegExpPattern = StrReplace(sRegExpPattern,"\)","")
sRegExpPattern = StrClean(sRegExpPattern,"()","",@TRUE,2)
iCount = StrLen(sRegExpPattern)
If (iCount mod 2) Then Return (-1)                  ; Error on matching brackets.
Return (iCount/2)
;...............................................................................................................................................
; If opening and closing round brackets do not match (odd count),
; then this udf returns -1 to indicate that there is an error
; on the SubMatching structure in the RegExpPattern.
; Otherwise this udf returns the number of SubMatching parenthesis pairs "()".
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetSubMatchCount (sMatchItem,sMatchPropSep)
Return (ItemCount(sMatchItem,sMatchPropSep)-3)
;...............................................................................................................................................
; This udf returns the number of SubMatch items per given MatchItem.
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetSubMatchValue (iSub, sMatchItem, sMatchPropSep)
If (sMatchPropSep == "") Then sMatchPropSep  = "|"
Return (ItemExtract(3 + iSub,sMatchItem,sMatchPropSep))
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetMatchCount (sMatchList, sMatchItemSep)
If (sMatchItemSep == "") Then sMatchItemSep = @TAB
Return (ItemCount(sMatchList,sMatchItemSep))
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetMatch (iMatch, sMatchList, sMatchItemSep)
If (sMatchItemSep == "") Then sMatchItemSep = @TAB
Return (ItemExtract(iMatch,sMatchList,sMatchItemSep))
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetMatchValue (sMatchItem, sMatchPropSep)
If (sMatchPropSep == "") Then sMatchPropSep  = "|"
Return (ItemExtract(1,sMatchItem,sMatchPropSep))
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetMatchIndex (sMatchItem, sMatchPropSep)
If (sMatchPropSep == "") Then sMatchPropSep  = "|"
Return (ItemExtract(2,sMatchItem,sMatchPropSep))
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetMatchLength (sMatchItem, sMatchPropSep)
If (sMatchPropSep == "") Then sMatchPropSep  = "|"
Return (ItemExtract(3,sMatchItem,sMatchPropSep))
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpTest (sSearchString, sRegExpPattern, bIgnoreCase)
bResult = @FALSE

iLastErrorMode = ErrorMode(@OFF)
LastError()
objRegExp = ObjectOpen("VBScript.RegExp")           ; Creates a regular expression object for use by WinBatch.
iResult = LastError()
ErrorMode(iLastErrorMode)
If iResult Then Goto LABELRETURN                    ; Object is not loadable.

objRegExp.Pattern    = sRegExpPattern               ; Set pattern.
objRegExp.IgnoreCase = bIgnoreCase                  ; Set case insensitivity. Default is @FALSE.

iLastErrorMode = ErrorMode(@OFF)
LastError()
bResult = !!objRegExp.Test(sSearchString)           ; vbTrue -1 True ; vbFalse 0 False
iResult = LastError()
ErrorMode(iLastErrorMode)
If iResult  Then Goto LABELOBJECTCLOSE              ; Maybe a pattern definition error.
If !bResult Then Goto LABELOBJECTCLOSE              ; There is no match.

:LABELOBJECTCLOSE
ObjectClose(objRegExp)
Drop(objRegExp)

:LABELRETURN
Return (bResult)
;...............................................................................................................................................
; This udf returns a boolean value depending on the check
; If the SearchString does have at least one match by RegExpPattern.
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpReplace (sSearchString, sRegExpPattern, sReplaceString, bIgnoreCase, bGlobalSearch)
sString = ""

iLastErrorMode = ErrorMode(@OFF)
LastError()
objRegExp = ObjectOpen("VBScript.RegExp")           ; Creates a regular expression object for use by WinBatch.
iResult = LastError()
ErrorMode(iLastErrorMode)
If iResult Then Goto LABELRETURN                    ; Object is not loadable.

objRegExp.Pattern    = sRegExpPattern               ; Set pattern.
objRegExp.IgnoreCase = bIgnoreCase                  ; Set case insensitivity. Default is @FALSE.
objRegExp.Global     = bGlobalSearch                ; Set global applicability. Default is @FALSE.

iLastErrorMode = ErrorMode(@OFF)
LastError()
bResult = !!objRegExp.Test(sSearchString)           ; vbTrue -1 True ; vbFalse 0 False
iResult = LastError()
ErrorMode(iLastErrorMode)
If iResult  Then Goto LABELOBJECTCLOSE              ; Maybe a pattern definition error.
If !bResult Then Goto LABELOBJECTCLOSE              ; There is no one match.

sString = objRegExp.Replace(sSearchString,sReplaceString) ; Make the replacement.

:LABELOBJECTCLOSE
ObjectClose(objRegExp)
Drop(objRegExp)

:LABELRETURN
Return (sString)
;...............................................................................................................................................
; Returns an empty string if there was an error on loading the VB Regular Expression OLE object.
; Returns an empty string if there was an error on the sRegExpPattern Test.
; If RegExpPattern does match, then this udf returns a copy of SearchString
; with the text of RegExpPattern replaced with ReplaceString.
; If no match is found, a copy of SearchString is returned unchanged.
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpMatch (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch, bMultiLine, sMatchPropSep, sMatchItemSep)
sMatchList = ""

iLastErrorMode = ErrorMode(@OFF)
LastError()
objRegExp = ObjectOpen("VBScript.RegExp")           ; Creates a regular expression object for use by WinBatch.
iResult = LastError()
ErrorMode(iLastErrorMode)
If iResult Then Goto LABELRETURN                    ; Object is not loadable.

objRegExp.Pattern    = sRegExpPattern               ; Set pattern.
objRegExp.IgnoreCase = bIgnoreCase                  ; Set case insensitivity. Default is @FALSE.
objRegExp.Global     = bGlobalSearch                ; Set global applicability. Default is @FALSE.
objRegExp.MultiLine  = bMultiLine                   ; Set MultiLine facility. Default is @FALSE.

iLastErrorMode = ErrorMode(@OFF)
LastError()
bResult = !!objRegExp.Test(sSearchString)           ; vbTrue -1 True ; vbFalse 0 False
iResult = LastError()
ErrorMode(iLastErrorMode)
If iResult  Then Goto LABELOBJECTCLOSE              ; Maybe a pattern definition error.
If !bResult Then Goto LABELOBJECTCLOSE              ; There is no one match.

iSubMatchCount = udfRegExpCheckPattern (sRegExpPattern)
If (iSubMatchCount < 0)  Then Goto LABELOBJECTCLOSE ; Maybe a SubMatch definition error.

If (sMatchPropSep == "") Then sMatchPropSep = "|"   ; Set separator between MatchItem properties
If (sMatchItemSep == "") Then sMatchItemSep = @TAB  ; Set separator between MatchItems

objMatches = objRegExp.Execute(sSearchString)       ; Executes the search. Returns a handle to a Matches collection.

sMatchList = ""
hEnum = ObjectCollectionOpen(objMatches)            ; Returns an enumeration handle.
While @TRUE
   sMatchItem = ""
   objMatch = ObjectCollectionNext(hEnum)           ; Returns a handle to one object which contains a match.
   If !objMatch Then Break

   ; Collect properties and build the MatchItem.
   sMatchItem = ItemInsert(objMatch.Value          ,-1,sMatchItem,sMatchPropSep)
   sMatchItem = ItemInsert(objMatch.FirstIndex + 1 ,-1,sMatchItem,sMatchPropSep) ; Force one based index.
   sMatchItem = ItemInsert(objMatch.Length         ,-1,sMatchItem,sMatchPropSep)

   ; Collect the SubMatches.
   objSubMatches = objMatch.SubMatches
   iSubMatchCountMax = objSubMatches.count - 1
   For iSubMatch=0 To iSubMatchCountMax
      sMatchItem = ItemInsert(objSubMatches.Item(iSubMatch),-1,sMatchItem,sMatchPropSep)
   Next
   ObjectClose(objSubMatches)

   ; Build the MatchList from MatchItems.
   sMatchList = ItemInsert(sMatchItem,-1,sMatchList,sMatchItemSep)

   ObjectClose(objMatch)
EndWhile
ObjectCollectionClose(hEnum)
Drop(objMatch,objSubMatches,hEnum)

ObjectClose(objMatches)
Drop(objMatches)

:LABELOBJECTCLOSE
ObjectClose(objRegExp)
Drop(objRegExp)

:LABELRETURN
Return (sMatchList)
;...............................................................................................................................................
; Returns an empty string if there was an error on loading the VB Regular Expression OLE object.
; Returns an empty string if there was no match on the search with Regular Expression pattern.
; If RegExpPattern does match, then this udf returns a tab delimited "MatchList" of one or more "MatchItems".
;...............................................................................................................................................
; A MatchItem is a structure of at least three properties: MatchValue, MatchIndex, MatchLength.
; Additionally there are appended SubMatchItems, when captured by the regular expression.
; A MatchItem for itself is a delimited list too, with pipe symbol "|" as default separator.
;
; Example:
; sSearchString  = "myabCthis is the second myabcthing"
; sRegExpPattern = "(a.*?c)"
; bIgnoreCase    = @true
; bGlobalSearch  = @true
; sMatchList = udfRegExp (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch, "", "")
;
; Resulting MatchList contains two MatchItems, each with one SubMatch:
; sMatchList = "abC|3|3|abC@TABabc|27|3|abc"
;
; If bGlobalSearch is @FALSE Then the resulting MatchList contains only the first MatchItem.
;...............................................................................................................................................
; Note:
; Collection Enumeration is zero based indexed.
; WIL String variables are indexed at 1.
;...............................................................................................................................................
; This udf is based on an article in WinBatch forum by Author "Jim Stiles 20020628 jwstiles@winbatch.com".
; Detlev Dalitz.20020703
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------
;===============================================================================================================================================



;===============================================================================================================================================
; 'Low Level' Routines      (VB Regular Expression object must be opened and closed manually.)
;===============================================================================================================================================
; udfRegExpOpen             ()                                                           ; Returns handle to RegExp object.
; udfRegExpClose            (hRegExp)
;
; udfRegExpGetPattern       (hRegExp)                                                    ; Returns pattern string.
; udfRegExpGetIgnoreCase    (hRegExp)                                                    ; Returns boolean value.
; udfRegExpGetGlobal        (hRegExp)                                                    ; Returns boolean value.
; udfRegExpGetMultiLine     (hRegExp)                                                    ; Returns boolean value.
;
; udfRegExpSetPattern       (hRegExp, sPattern)
; udfRegExpSetIgnoreCase    (hRegExp, bIgnoreCase)
; udfRegExpSetGlobal        (hRegExp, bGlobalSearch)
; udfRegExpSetMultiLine     (hRegExp, bMultiLine)
;
; udfRegExpTestString       (hRegExp, sSearchString)                                     ; Returns boolean value.
; udfRegExpMatchString      (hRegExp, sSearchString, sMatchPropSep, sMatchItemSep)       ; Returns MatchList like udfRegExpMatch.
; udfRegExpReplaceString    (hRegExp, sSearchString, sReplaceString)                     ; Returns replaced string.
;===============================================================================================================================================


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpOpen ()
iLastErrorMode = ErrorMode(@OFF)
LastError()
objRegExp = ObjectOpen("VBScript.RegExp") ; Creates a regular expression object for use by WinBatch.
iResult = LastError()
ErrorMode(iLastErrorMode)
Return (objRegExp)
;...............................................................................................................................................
; This udf returns a handle to a RegExp object.
; On error it returns 0.
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpClose (hRegExp)
Return (ObjectClose(hRegExp))
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetPattern (hRegExp)
Return (hRegExp.Pattern)
; This udf returns the current pattern setting on a given object handle.
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetIgnoreCase (hRegExp)
Return (!!hRegExp.IgnoreCase)                       ; vbTrue = -1 ; vbFalse = 0
; This udf returns the current bIgnoreCase setting on a given object handle.
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetGlobal (hRegExp)
Return (!!hRegExp.Global)                           ; vbTrue = -1 ; vbFalse = 0
; This udf returns the current Global setting on a given object handle.
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpGetMultiline (hRegExp)
Return (!!hRegExp.MultiLine)                        ; vbTrue = -1 ; vbFalse = 0
; This udf returns the current bMultiLine setting on a given object handle.
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpSetPattern (hRegExp, sPattern)
hRegExp.Pattern = sPattern
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpSetIgnoreCase (hRegExp, bValue)
hRegExp.IgnoreCase = bValue
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpSetGlobal (hRegExp, bValue)
hRegExp.Global = bValue
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpSetMultiline (hRegExp, bValue)
hRegExp.MultiLine = bValue
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpTestString (hRegExp, sSearchString)
iLastErrorMode = ErrorMode(@OFF)
LastError()
bResult = !!hRegExp.Test(sSearchString)             ; vbTrue -1 True ; vbFalse 0 False
iResult = LastError()
ErrorMode(iLastErrorMode)
If iResult  Then Return (@FALSE)                    ; Maybe a pattern definition error.
If !bResult Then Return (@FALSE)                    ; There is no match.
Return (bResult)
;...............................................................................................................................................
; This udf returns a boolean value depending on the check
; if the sSearchString does have at least one match by previously defined sRegExpPattern.
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpReplaceString (hRegExp, sSearchString, sReplaceString)
Return (hRegExp.Replace(sSearchString,sReplaceString))
;...............................................................................................................................................
; If previously defined RegExpPattern does match, then this udf returns a copy of SearchString
; with the text of RegExpPattern replaced with ReplaceString.
; If no match is found, a copy of sSearchString is returned unchanged.
;...............................................................................................................................................
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------


;-----------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfRegExpMatchString (hRegExp, sSearchString, sMatchPropSep, sMatchItemSep)
sMatchList = ""

iSubMatchCount = udfRegExpCheckPattern (sRegExpPattern)
If (iSubMatchCount < 0)  Then Return ("")           ; Maybe a SubMatch definition error.

If (sMatchPropSep == "") Then sMatchPropSep = "|"   ; Set separator between MatchItem properties.
If (sMatchItemSep == "") Then sMatchItemSep = @TAB  ; Set separator between MatchItems.

objMatches = hRegExp.Execute(sSearchString)         ; Executes the search. Returns a handle to a Matches collection.

sMatchList = ""
hEnum = ObjectCollectionOpen(objMatches)            ; Returns an enumeration handle.
While @TRUE
   sMatchItem = ""
   objMatch = ObjectCollectionNext(hEnum)           ; Returns a handle to one object which contains a match.
   If !objMatch Then Break

   ; Collect properties and build the MatchItem.
   sMatchItem = ItemInsert(objMatch.Value          ,-1,sMatchItem,sMatchPropSep)
   sMatchItem = ItemInsert(objMatch.FirstIndex + 1 ,-1,sMatchItem,sMatchPropSep) ; Force one based index.
   sMatchItem = ItemInsert(objMatch.Length         ,-1,sMatchItem,sMatchPropSep)

   ; Collect the SubMatches.
   objSubMatches = objMatch.SubMatches
   iSubMatchCountMax = objSubMatches.count - 1
   For iSubMatch=0 To iSubMatchCountMax
      sMatchItem = ItemInsert(objSubMatches.Item(iSubMatch),-1,sMatchItem,sMatchPropSep)
   Next
   ObjectClose(objSubMatches)

   ; Build the MatchList from MatchItems.
   sMatchList = ItemInsert(sMatchItem,-1,sMatchList,sMatchItemSep)

   ObjectClose(objMatch)
EndWhile
ObjectCollectionClose(hEnum)
Drop(objMatch,objSubMatches,hEnum)

ObjectClose(objMatches)
Drop(objMatches)

Return (sMatchList)
#EndFunction
;-----------------------------------------------------------------------------------------------------------------------------------------------
;===============================================================================================================================================




; --- test ---

;-----------------------------------------------------------------------------------------------------------------------------------------------
:test1
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Check if e-mail address format is ok or not.

sSearchString  = "dd@dalitz-im-netz.de"
sRegExpPattern = "([\w\-]+)@([\w\-]+)\.([\w\-]+)"
bIgnoreCase    = @TRUE ; Default is @FALSE.

iMatched = udfRegExpTest (sSearchString, sRegExpPattern, bIgnoreCase)

sNoYes   = ItemExtract(1+iMatched,"no,yes",",")
sMsgText = StrCat("SearchString matches RegExpPattern =" ,@TAB,sNoYes,@LF)
sMsgText = StrCat("IgnoreCase ="   ,@TAB,bIgnoreCase   ,@LF,sMsgText,@LF)
sMsgText = StrCat("RegExpPattern =",@TAB,sRegExpPattern,@LF,sMsgText,@LF)
sMsgText = StrCat("SearchString =" ,@TAB,sSearchString ,@LF,sMsgText,@LF)

sMsgTitle = "Demo  udfRegExpTest (sSearchString, sRegExpPattern, bIgnoreCase)"
IntControl (63,150,200,850,700)
AskItemlist(sMsgTitle,sMsgText,@LF,@UNSORTED,@SINGLE)



;-----------------------------------------------------------------------------------------------------------------------------------------------
:test2
;-----------------------------------------------------------------------------------------------------------------------------------------------
; This script uses a regular expression pattern
; to find all the matches for a given pattern
; and returns the matches in a WIL list variable.
; It is an example that shows how the Visual Basic Regular Expression
; capability can be used from WinBatch.
; Original script by Author: "Jim Stiles 20020628".

; String with several possible matches for the expression pattern.
; sSearchString = "myabCthis is the second myabcthing"
; Match from the first a to and including the next c.
; To exclude the c, try [^c]* in place of .*? .
; To select the string from the first a to the first c, use the ?.
; Without the ?, the expression would select a string from the first a to the final, and third, c.

sSearchString  = "myabCthis is the second myabcthing"
sRegExpPattern = "(a.*?c)"

bIgnoreCase    = @TRUE  ; Default is @FALSE.
bGlobalSearch  = @TRUE  ; Default is @FALSE.
bMultiLine     = @FALSE ; Default is @FALSE.

sMatchPropSep = "|"
sMatchListSep = @TAB

sMatchList = udfRegExpMatch (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch, bMultiLine, sMatchPropSep, sMatchListSep)

iCount = udfRegExpGetMatchCount (sMatchList, sMatchListSep)
sMsgText  = ""
For i=1 To iCount
   sMatch  = udfRegExpGetMatch (i, sMatchList, sMatchListSep)
   sValue  = udfRegExpGetMatchValue  (sMatch, sMatchPropSep)
   iIndex  = udfRegExpGetMatchIndex  (sMatch, sMatchPropSep)
   iLength = udfRegExpGetMatchLength (sMatch, sMatchPropSep)

   sMsgText  = StrCat(sMsgText,"Value =" ,@TAB,sValue ,@TAB)
   sMsgText  = StrCat(sMsgText,"Index =" ,@TAB,iIndex ,@TAB)
   sMsgText  = StrCat(sMsgText,"Length =",@TAB,iLength,@TAB)
   sMsgText  = StrCat(sMsgText,@LF)
Next
sMsgText = StrCat("GlobalSearch =" ,@TAB,bGlobalSearch ,@LF,@LF,sMsgText,@LF)
sMsgText = StrCat("IgnoreCase ="   ,@TAB,bIgnoreCase   ,@LF,sMsgText,@LF)
sMsgText = StrCat("MultiLine ="    ,@TAB,bMultiLine    ,@LF,sMsgText,@LF)
sMsgText = StrCat("RegExpPattern =",@TAB,sRegExpPattern,@LF,sMsgText,@LF)
sMsgText = StrCat("SearchString =" ,@TAB,sSearchString ,@LF,sMsgText,@LF)

sMsgTitle = "Demo  udfRegExpFind (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch, sMatchPropSep, sMatchItemSep)"
IntControl (63,150,200,850,700)
AskItemlist(sMsgTitle,sMsgText,@LF,@UNSORTED,@SINGLE)



;-----------------------------------------------------------------------------------------------------------------------------------------------
:test3
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Check e-mail address and separate it into three parts.

sSearchString  = "Please send mail to drag_on@x-yz-zy.com. Thanks!"
sRegExpPattern = "([\w\-]+)@([\w\-]+)\.([\w\-]+)"
;sRegExpPattern = "([\w])+" ; Test it!

;bIgnoreCase    = @FALSE
;bGlobalSearch  = @FALSE
;bMultiLine     = @FALSE

bIgnoreCase    = @TRUE
bGlobalSearch  = @TRUE
bMultiLine     = @FALSE

sMatchPropSep = "|"
sMatchListSep = @TAB

sMatchList  = udfRegExpMatch (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch, bMultiLine, sMatchPropSep, sMatchListSep)
iMatchCount = udfRegExpGetMatchCount (sMatchList, sMatchListSep)

sMsgText  = ""

For iMatch=1 To iMatchCount
   sMatch  = udfRegExpGetMatch (iMatch, sMatchList, sMatchListSep)
   sValue  = udfRegExpGetMatchValue  (sMatch, sMatchPropSep)
   iIndex  = udfRegExpGetMatchIndex  (sMatch, sMatchPropSep)
   iLength = udfRegExpGetMatchLength (sMatch, sMatchPropSep)

   sMsgText  = StrCat(sMsgText,'Value'  ,@TAB,' = ','"',sValue ,'"',@TAB)
   sMsgText  = StrCat(sMsgText,'Index'  ,@TAB,' = ','"',iIndex ,'"',@TAB)
   sMsgText  = StrCat(sMsgText,'Length' ,@TAB,' = ','"',iLength,'"',@TAB)
   sMsgText  = StrCat(sMsgText,@LF)

   iSubCount = udfRegExpGetSubMatchCount (sMatch, sMatchPropSep)
   For iSub=1 To iSubCount
      sSubMatch = udfRegExpGetSubMatchValue (iSub, sMatch, sMatchPropSep)
      sMsgText = StrCat(sMsgText,'SubMatch',iSub,@TAB,' = ','"',sSubMatch,'"',@LF)
   Next
Next

sMsgText = StrCat('GlobalSearch' ,@TAB,' = ','"',bGlobalSearch ,'"',@LF,@LF,sMsgText,@LF)
sMsgText = StrCat('IgnoreCase'   ,@TAB,' = ','"',bIgnoreCase   ,'"',@LF,sMsgText,@LF)
sMsgText = StrCat('RegExpPattern',@TAB,' = ','"',sRegExpPattern,'"',@LF,sMsgText,@LF)
sMsgText = StrCat('SearchString' ,@TAB,' = ','"',sSearchString ,'"',@LF,sMsgText,@LF)

sMsgTitle = "Demo  udfRegExp (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch, sMatchPropSep, sMatchItemSep)"
IntControl (63,150,200,850,700)
AskItemlist(sMsgTitle,sMsgText,@LF,@UNSORTED,@SINGLE)



;-----------------------------------------------------------------------------------------------------------------------------------------------
:test4
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Replace one word with another word.

sSearchString  = "The quick brown fox jumped over the lazy dog."
sRegExpPattern = "fox"
sReplaceString = "cat"

bIgnoreCase    = @TRUE
bGlobalSearch  = @FALSE

sReplacedString = udfRegExpReplace (sSearchString, sRegExpPattern, sReplaceString, bIgnoreCase, bGlobalSearch)

sMsgTitle = "Demo  udfRegExpReplace (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch)"
sMsgText = ""
sMsgText = StrCat(sMsgText,'SearchString'  ,@TAB,' = ','"',sSearchString  ,'"',@LF)
sMsgText = StrCat(sMsgText,'RegExpPattern' ,@TAB,' = ','"',sRegExpPattern ,'"',@LF)
sMsgText = StrCat(sMsgText,'ReplaceString' ,@TAB,' = ','"',sReplaceString ,'"',@LF)
sMsgText = StrCat(sMsgText,'IgnoreCase'    ,@TAB,' = ','"',bIgnoreCase    ,'"',@LF)
sMsgText = StrCat(sMsgText,'GlobalSearch'  ,@TAB,' = ','"',bGlobalSearch  ,'"',@LF)
sMsgText = StrCat(sMsgText,'ReplacedString',@TAB,' = ','"',sReplacedString,'"',@LF)
IntControl (63,150,200,850,700)
AskItemlist(sMsgTitle,sMsgText,@LF,@UNSORTED,@SINGLE)



;-----------------------------------------------------------------------------------------------------------------------------------------------
:test5
;-----------------------------------------------------------------------------------------------------------------------------------------------
; In addition, the Replace method can replace subexpressions in the pattern.
; The following script swaps each pair of words in the original string

sSearchString  = "The quick brown fox jumped over the lazy dog."
sRegExpPattern = "(\S+)(\s+)(\S+)" ; Swap pairs of words.
sReplaceString = "$3$2$1"

bIgnoreCase    = @TRUE
bGlobalSearch  = @TRUE

sReplacedString = udfRegExpReplace (sSearchString, sRegExpPattern, sReplaceString, bIgnoreCase, bGlobalSearch)

sMsgTitle = "Demo  udfRegExpReplace (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch)"
sMsgText = ""
sMsgText = StrCat(sMsgText,'SearchString'  ,@TAB,' = ','"',sSearchString  ,'"',@LF)
sMsgText = StrCat(sMsgText,'RegExpPattern' ,@TAB,' = ','"',sRegExpPattern ,'"',@LF)
sMsgText = StrCat(sMsgText,'ReplaceString' ,@TAB,' = ','"',sReplaceString ,'"',@LF)
sMsgText = StrCat(sMsgText,'IgnoreCase'    ,@TAB,' = ','"',bIgnoreCase    ,'"',@LF)
sMsgText = StrCat(sMsgText,'GlobalSearch'  ,@TAB,' = ','"',bGlobalSearch  ,'"',@LF)
sMsgText = StrCat(sMsgText,'ReplacedString',@TAB,' = ','"',sReplacedString,'"',@LF)
IntControl (63,150,200,850,700)
AskItemlist(sMsgTitle,sMsgText,@LF,@UNSORTED,@SINGLE)



;-----------------------------------------------------------------------------------------------------------------------------------------------
:test6
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Set and query RegExp properties.

objRegExp = udfRegExpOpen ()

If (objRegExp <> 0)

   udfRegExpSetPattern(objRegExp,"( *)next( *)")
   udfRegExpSetIgnoreCase(objRegExp, @TRUE)
   udfRegExpSetGlobal(objRegExp, @FALSE)
   udfRegExpSetMultiline(objRegExp, @TRUE)


   sMsgTitle = "Demo  udfRegExpGetPattern ()"
   sMsgText = ""
   sMsgText = StrCat(sMsgText,'RegExpPattern' ,@TAB,' = ','"',udfRegExpGetPattern(objRegExp)   ,'"',@LF)
   sMsgText = StrCat(sMsgText,'IgnoreCase'    ,@TAB,' = ','"',udfRegExpGetIgnoreCase(objRegExp),'"',@LF)
   sMsgText = StrCat(sMsgText,'GlobalSearch'  ,@TAB,' = ','"',udfRegExpGetGlobal(objRegExp)    ,'"',@LF)
   sMsgText = StrCat(sMsgText,'MultiLine'     ,@TAB,' = ','"',udfRegExpGetMultiline(objRegExp) ,'"',@LF)
   IntControl (63,150,200,850,700)
   AskItemlist(sMsgTitle,sMsgText,@LF,@UNSORTED,@SINGLE)

   udfRegExpClose (objRegExp)
EndIf



;-----------------------------------------------------------------------------------------------------------------------------------------------
:test7
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Replace control character.

sSearchString  = StrCat("Control",@CR,"characters",@LF,"can also be indicated",@CR,@LF,"by RegExp pattern.",@CRLF)
sRegExpPattern = "(\cM\cJ)|(\cJ)|(\cM)" ; @cr@lf or @lf or @cr
sReplaceString = "<BR>"

bIgnoreCase    = @TRUE
bGlobalSearch  = @TRUE

sReplacedString = udfRegExpReplace (sSearchString, sRegExpPattern, sReplaceString, bIgnoreCase, bGlobalSearch)

sMsgTitle = "Demo  udfRegExpReplace (sSearchString, sRegExpPattern, bIgnoreCase, bGlobalSearch)"
sMsgText = ""
sMsgText = StrCat(sMsgText,'SearchString'  ,@TAB,' = ','"',sSearchString  ,'"',@LF)
sMsgText = StrCat(sMsgText,'RegExpPattern' ,@TAB,' = ','"',sRegExpPattern ,'"',@LF)
sMsgText = StrCat(sMsgText,'ReplaceString' ,@TAB,' = ','"',sReplaceString ,'"',@LF)
sMsgText = StrCat(sMsgText,'IgnoreCase'    ,@TAB,' = ','"',bIgnoreCase    ,'"',@LF)
sMsgText = StrCat(sMsgText,'GlobalSearch'  ,@TAB,' = ','"',bGlobalSearch  ,'"',@LF)
sMsgText = StrCat(sMsgText,'ReplacedString',@TAB,' = ','"',sReplacedString,'"',@LF)
IntControl (63,150,200,850,700)
AskItemlist(sMsgTitle,sMsgText,@LF,@UNSORTED,@SINGLE)


;-----------------------------------------------------------------------------------------------------------------------------------------------
:CANCEL
Exit
;===============================================================================================================================================








;===============================================================================================================================================
; Requirements
;===============================================================================================================================================
; This WIL User Defined Function library is based on the OLE object "VBScript.RegExp".
; It requires "Microsoft Visual Basic Scripting Edition Version 5.0/5.5"
; implemented by Host Application  "Microsoft Internet Explorer 5.0/5.5".
; The SubMatch collection requires "Microsoft Visual Basic Scripting Edition Version 5.5"
; The MultiLine property  requires "Microsoft Visual Basic Scripting Edition Version 5.5"
; Some Replace Properties require  "Microsoft Internet Explorer 5.5" or "Microsoft Windows Millennium Edition"
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Original documentation adapted from the Microsoft Platform SDK, May 2002 Edition.
;===============================================================================================================================================



;===============================================================================================================================================
; Here are some examples of regular expression you might encounter
;===============================================================================================================================================
; Match a blank line.
; "^\s*$"
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Validate an ID number consisting of 2 digits, a hyphen, and another 5 digits.
; "\d{2}-\d{5}"
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Validate an email address in the format "name@host.org".
; "([\w\-]+)@([\w\-]+)\.([\w\-]+)"
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Match "industry" or "industries" (non-capturing match).
; "industr(?:y|ies)"
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Match "Windows" in "Windows 2000" but not "Windows" in "Windows 3.1"
; (non-capturing match, positive lookahead).
; "Windows (?=95|98|NT|2000)"
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Match "Windows" in "Windows 3.1" but does not match "Windows" in "Windows 2000"
; (non-capturing match, negative lookahead).
; "Windows (?!95|98|NT|2000)"
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Match the copyright symbol (©).
; "\u00A9"
;===============================================================================================================================================



;===============================================================================================================================================
; Additional notes from the MS SDK, Visual Basic Scripting Edition
;===============================================================================================================================================
; ObjectRegExp.Pattern [= "searchstring"]
; The "Pattern Property" sets or returns the regular expression pattern being searched for.
; Optional searchstring is a regular string expression being searched for.
; May include any of the regular expression characters defined in the table in the "Settings" section.
;
; ObjectRegExp.IgnoreCase [= True | False ]
; The "IgnoreCase Property" sets or returns a Boolean value that indicates
; if a pattern search is case-sensitive or not.
; The value of the IgnoreCase property is False if the search is case-sensitive,
; True if it is not. Default is False.
;
; ObjectRegExp.Global [= True | False ]
; The "Global Property" sets or returns a Boolean value that indicates
; if a pattern should match all occurrences in an entire search string or just the first one.
; The object argument is always a RegExp object.
; The value of the Global property is True if the search applies to the entire string,
; False if it does not. Default is False.
;
; ObjectRegExp.MultiLine [= True | False ]
; ???
; If MultiLine is false,
; "^" matches the position at the beginning of a string, and
; "$" matches the position at the end of a string.
; If multline is true,
; "^" matches the position at the beginning of a string as well as the position following a "\n" or "\r",
; and  "$" matches the position at the end of a string and the position preceding "\n" or "\r".
; Default is False.
;
; ObjectRegExp.Execute (string)
; ???
;
; ObjectRegExp.Test (string)
; The "Test Method" executes a regular expression search against a specified string
; and returns a Boolean value that indicates if a pattern match was found.
; The actual pattern for the regular expression search is set using the Pattern property of the RegExp object.
; The RegExp.Global property has no effect on the Test method.
; The Test method returns True if a pattern match is found; False if no match is found.
;
; ObjectRegExp.Replace (string1, string2)
; The Replace Method replaces text found in a regular expression search.
; String1 is the text string in which the text replacement is to occur.
; String2 is the replacement text string.
; The actual pattern for the text being replaced is set using the Pattern property of the RegExp object.
; The Replace method returns a copy of string1 with the text of RegExp.Pattern replaced with string2.
; If no match is found, a copy of string1 is returned unchanged.
;
; In addition, the Replace method can replace subexpressions in the pattern.
; e.g. ObjectRegExp.Replace("(\S+)(\s+)(\S+)", "$3$2$1")) swaps pairs of words.
; For further details see "Replace Properties" section.
;
;===============================================================================================================================================



;===============================================================================================================================================
; Settings
;-----------------------------------------------------------------------------------------------------------------------------------------------
; Special characters and sequences are used in writing patterns for regular expressions.
; The following table describes and gives an example of the characters and sequences that can be used.
;
;   Character    Description
;
;   \            Marks the next character as a special character, a literal, a backreference, or an octal escape.
;                   For example, "n" matches the character "n".
;                   "\n" matches a newline character.
;                   The sequence "\\" matches "\" and "\(" matches "(".
;
;   ^            Matches the position at the beginning of the input string.
;                   If the RegExp object's MultiLine property is set,
;                   ^ also matches the position following "\n" or "\r".
;
;   $            Matches the position at the end of the input string.
;                   If the RegExp object's MultiLine property is set,
;                   $ also matches the position preceding "\n" or "\r".
;
;   *            Matches the preceding character zero or more times.
;                   For example, "zo*" matches either "z" or "zoo".
;                   * is equivalent to "{0,}".
;
;   +            Matches the preceding character one or more times.
;                   For example, "zo+" matches "zoo" but not "z".
;                   + is equivalent to "{1,}".
;
;   ?            Matches the preceding character zero or one time.
;                   For example, "a?ve?" matches the "ve" in "never".
;                   For example, "do(es)?" matches the "do" in "do" or "does".
;                   ? is equivalent to "{0,1}"
;                   When this character immediately follows any of the other quantifiers
;                   (*, +, ?, {n}, {n,}, {n,m}), the matching pattern is non-greedy.
;                   A non-greedy pattern matches as little of the searched string as possible,
;                   whereas the default greedy pattern matches as much of the searched string as possible.
;                   For example, in the string "oooo", 'o+?' matches a single "o", while 'o+' matches all 'o's.
;
;   .            Matches any single character except a newline character "\n".
;                   To match any character including the "\n", use a pattern such as "[\s\S]".
;
;   (pattern)    Matches pattern and remembers the match.
;                   The matched substring can be retrieved from the resulting Matches collection, using Item [0]...[n].
;                   To match parentheses characters ( ), use "\(" or "\)".
;
;   (?:pattern)  Matches pattern but does not capture the match,
;                   that is, it is a non-capturing match that is not stored for possible later use.
;                   This is useful for combining parts of a pattern with the "or" character (|).
;                   For example, 'industr(?:y|ies) is a more economical expression than 'industry|industries'.
;
;   (?=pattern)  Positive lookahead matches the search string at any point where a string matching pattern begins.
;                   This is a non-capturing match, that is, the match is not captured for possible later use.
;                   For example 'Windows (?=95|98|NT|2000)' matches "Windows" in "Windows 2000"
;                   but not "Windows" in "Windows 3.1".
;                   Lookaheads do not consume characters, that is, after a match occurs,
;                   the search for the next match begins immediately following the last match,
;                   not after the characters that comprised the lookahead.
;
;   (?!pattern)  Negative lookahead matches the search string at any point where a string not matching pattern begins.
;                   This is a non-capturing match, that is, the match is not captured for possible later use.
;                   For example 'Windows (?!95|98|NT|2000)' matches "Windows" in "Windows 3.1"
;                   but does not match "Windows" in "Windows 2000".
;                   Lookaheads do not consume characters, that is, after a match occurs,
;                   the search for the next match begins immediately following the last match,
;                   not after the characters that comprised the lookahead.
;
;   x|y          Matches either x or y. For example, 'z|food' matches "z" or "food". '(z|f)ood' matches "zood" or "food".
;
;   {n}          n is a nonnegative integer.
;                   Matches exactly n times.
;                   For example, "o{2}" does not match the "o" in "Bob," but matches the first two o's in "foooood".
;
;   {n,}         n is a nonnegative integer.
;                   Matches at least n times.
;                   For example, "o{2,}" does not match the "o" in "Bob" and matches all the o's in "foooood."
;                   "o{1,}" is equivalent to "o+".
;                   "o{0,}" is equivalent to "o*".
;
;   {n,m}        m and n are nonnegative integers, where n <= m.
;                   Matches at least n and at most m times.
;                   For example, "o{1,3}" matches the first three o's in "fooooood".
;                   "o{0,1}" is equivalent to "o?".
;                   Note that you cannot put a space between the comma and the numbers.
;
;   [xyz]        A character set. Matches any one of the enclosed characters.
;                   For example, "[abc]" matches the "a" in "plain".
;
;   [^xyz]       A negative character set. Matches any character not enclosed.
;                   For example, "[^abc]" matches the "p" in "plain".
;
;   [a-z]        A range of characters. Matches any character in the specified range.
;                   For example, "[a-z]" matches any lowercase alphabetic character in the range "a" through "z".
;
;   [^m-z]       A negative range characters. Matches any character not in the specified range.
;                   For example, "[m-z]" matches any character not in the range "m" through "z".
;
;   \b           Matches a word boundary, that is, the position between a word and a space.
;                   For example, "er\b" matches the "er" in "never" but not the "er" in "verb".
;
;   \B           Matches a non-word boundary. "ea*r\B" matches the "ear" in "never early".
;
;   \d           Matches a digit character. Equivalent to "[0-9]".
;
;   \D           Matches a non-digit character. Equivalent to "[^0-9]".
;
;   \f           Matches a form-feed character. Equivalent to "\x0c" and "\cL".
;
;   \n           Matches a newline character. Equivalent to "\x0a" and "\cJ".
;
;   \r           Matches a carriage return character. Equivalent to "\x0d" and "\cM".
;
;   \s           Matches any white space including space, tab, form-feed, etc. Equivalent to "[ \f\n\r\t\v]".
;
;   \S           Matches any nonwhite space character. Equivalent to "[^ \f\n\r\t\v]".
;
;   \t           Matches a tab character. Equivalent to "\x09" and "\cI".
;
;   \v           Matches a vertical tab character. Equivalent to "\x0b" and "\cK".
;
;   \w           Matches any word character including underscore. Equivalent to "[A-Za-z0-9_]".
;
;   \W           Matches any non-word character. Equivalent to "[^A-Za-z0-9_]".
;
;   \num         Matches num, where num is a positive integer. A reference back to remembered matches.
;                   For example, "(.)\1" matches two consecutive identical characters.
;                   If \num is preceded by at least num captured subexpressions, num is a backreference.
;                   Otherwise, num is an octal escape value if num is an octal digit (0-7).
;
;   \n           Matches n, where n is an octal escape value. Octal escape values must be 1, 2, or 3 digits long.
;                   For example, "\11" and "\011" both match a tab character.
;                   "\0011" is the equivalent of "\001" & "1". Octal escape values must not exceed 256.
;                   If they do, only the first two digits comprise the expression.
;                   Allows ASCII codes to be used in regular expressions.
;
;   \nm          Identifies either an octal escape value or a backreference.
;                   If \nm is preceded by at least nm captured subexpressions, nm is a backreference.
;                   If \nm is preceded by at least n captures, n is a backreference followed by literal m.
;                   If neither of the preceding conditions exist,
;                   \nm matches octal escape value nm when n and m are octal digits (0-7).
;
;   \nml         Matches octal escape value nml when n is an octal digit (0-3) and m and l are octal digits (0-7).
;
;   \xn          Matches n, where n is a hexadecimal escape value.
;                   Hexadecimal escape values must be exactly two digits long.
;                   For example, "\x41" matches "A". "\x041" is equivalent to "\x04" & "1".
;                   Allows ASCII codes to be used in regular expressions.
;
;   \cx          Matches the control character indicated by x.
;                   For example, \cM matches a Control-M or carriage return character.
;                   The value of x must be in the range of A-Z or a-z.
;                   If not, c is assumed to be a literal 'c' character.
;
;   \un          Matches n, where n is a Unicode character expressed as four hexadecimal digits.
;                   For example, \u00A9 matches the copyright symbol (©).
;
;===============================================================================================================================================



;===============================================================================================================================================
; Replace Properties
;-----------------------------------------------------------------------------------------------------------------------------------------------
;   $1...$9      $1...$9 properties
;                   Returns the nine most-recently memorized portions found during pattern matching. Read-only.
;                   The value of the $1...$9 properties is modified whenever a successful parenthesized match is made.
;                   Any number of parenthesized substrings may be specified in a regular expression pattern,
;                   but only the nine most recent can be stored.
;
;   $_           input Property
;                   Returns the string against which a regular expression search was performed. Read-only.
;                   The value of input property is modified any time the searched string is changed.
;
;   $&           lastMatch Property
;                   Returns the last matched characters from any regular expression search. Read-only.
;                   The initial value of the lastMatch property is an empty string.
;                   The value of the lastMatch property changes whenever a successful match is made.
;
;   $+           lastParen Property
;                   Returns the last parenthesized submatch from any regular expression search, if any. Read-only.
;                   The initial value of the lastParen property is an empty string.
;                   The value of the lastParen property changes whenever a successful match is made.
;
;   $`           leftContext Property
;                   Returns the characters from the beginning of a searched string
;                   up to the position before the beginning of the last match. Read-only.
;                   The initial value of the leftContext property is an empty string.
;                   The value of the leftContext property changes whenever a successful match is made.
;
;   $'           rightContext Property
;                   Returns the characters from the position following the last match to the end of the searched string. Read-only.
;                   The initial value of the rightContext property is an empty string.
;                   The value of the rightContext property changes whenever a successful match is made.
;
;===============================================================================================================================================



;===============================================================================================================================================
; Control Characters Table
;===============================================================================================================================================
;  Decimal     Binary  Hex   Ascii   Key
;
;        0   00000000   00   NUL
;        1   00000001   01   SOH     ^A
;        2   00000010   02   STX     ^B
;        3   00000011   03   ETX     ^C
;        4   00000100   04   EOT     ^D
;        5   00000101   05   ENQ     ^E
;        6   00000110   06   ACK     ^F
;        7   00000111   07   BEL     ^G
;        8   00001000   08   BS      ^H
;        9   00001001   09   HT      ^I
;       10   00001010   0A   LF      ^J
;       11   00001011   0B   VT      ^K
;       12   00001100   0C   FF      ^L
;       13   00001101   0D   CR      ^M
;       14   00001110   0E   SO      ^N
;       15   00001111   0F   SI      ^O
;       16   00010000   10   DLE     ^P
;       17   00010001   11   DC1     ^Q
;       18   00010010   12   DC2     ^R
;       19   00010011   13   DC3     ^S
;       20   00010100   14   DC4     ^T
;       21   00010101   15   NAK     ^U
;       22   00010110   16   SYN     ^V
;       23   00010111   17   ETB     ^W
;       24   00011000   18   CAN     ^X
;       25   00011001   19   EM      ^Y
;       26   00011010   1A   SUB     ^Z
;       27   00011011   1B   ESC     ^[
;       28   00011100   1C   FS      ^\
;       29   00011101   1D   GS      ^]
;       30   00011110   1E   RS      ^^
;       31   00011111   1F   US      ^_
;===============================================================================================================================================
;*EOF*