I am doing this now with Instr/Split but have found regex in general to be much faster (this is an inner loop with 100K+ tests per run).
The general form is:
word0 = word1, word2, word3...
There are one or more words to the right of =. A word is defined as [\w.-]+. I need to allow for whitespace at any point as well. The = is required.
I want to return just word1, word2 and word3 in the Matches collection.
The = is what has me stumped. I either get one match or none depending on the pattern.
Here is some test code. Change RE.Pattern on line 17 to test.
Option Explicit
Test1 "word1, word2",""
Test1 " word0 = word1, word.2 , word3.qrs_t-1", "word1 word.2 word3.qrs_t-1"
Test1 "word0=word1", "word1"
WScript.Quit
Sub Test1(TestString, CorrectOutput)
Dim RE, Matches, Answer
Dim i, j
Set RE = New RegExp
RE.Global = True
RE.Pattern = "=([\w.-]+)"
Set Matches = RE.Execute(TestString)
Answer = "Input: " & vbTab & TestString & vbLf
Answer = Answer & "Correct:" & vbTab & CorrectOutput & vbLf
Answer = Answer & "Actual: " & vbTab
For i = 0 To Matches.Count -1
If i > 0 Then
Answer = Answer & " "
End If
Answer = Answer & Matches(i).value
Next
MsgBox Answer
End Sub
Use the following regular expression to extract the the substring with the wordlist from the input string:
str = "..."
Set re = New RegExp
re.Pattern = "^.*?=((?:[^,]+)(?:,[^,]+)*)"
re.Global = True
Set m = re.Execute(str)
Then use a second expression to remove the separating commas and mangle the whitespace:
Set re2 = New RegExp
re2.Pattern = "\s*,\s*"
re2.Global = True
wordlist = ""
If m.Count > 0 Then
wordlist = Trim(re2.Replace(m(0).SubMatches(0), " "))
End If
WScript.Echo wordlist
Description
Give this a try, it'll:
require a value before the equals sign
require an equals sign
require at least 1 value after the equals sign
return each of the 1 to 3 comma delimited chunks of text
trim spaces off all returned values
(?:^\s*?(\b[^=]*?\b)(?:\s{0,}[=]\s{0,}))(?:(['"]?)(\b[^,]*\b)\2\s*?)(?:$|(?:[,]\s*?(['"]?)(\b[^,]*\b)\4\s*?)(?:$|[,]\s*?(['"]?)(\b[^,]*\b)\6\s*?$))
(Right click the image and select view in new tab or new window for full size)
Groups
group 0 matches the full string if it's valid
groups 1-7
value before the equals sign
Quote delimiter if there was one for value 1
first value in the list of values
Quote delimiter if there was one for value 2
second value in the list of values
Quote delimiter if there was on for value 3
third value in the list of values
VB.NET Code Example to demonstrate the that the regex works
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim sourcestring as String = "replace with your source string"
Dim re As Regex = New Regex("(?:^\s*?(\b[^=]*?\b)(?:\s{0,}[=]\s{0,}))(?:(['"]?)(\b[^,]*\b)\2\s*?)(?:$|(?:[,]\s*?(['"]?)(\b[^,]*\b)\4\s*?)(?:$|[,]\s*?(['"]?)(\b[^,]*\b)\6\s*?$))",RegexOptions.IgnoreCase OR RegexOptions.Multiline OR RegexOptions.Singleline)
Dim mc as MatchCollection = re.Matches(sourcestring)
Dim mIdx as Integer = 0
For each m as Match in mc
For groupIdx As Integer = 0 To m.Groups.Count - 1
Console.WriteLine("[{0}][{1}] = {2}", mIdx, re.GetGroupNames(groupIdx), m.Groups(groupIdx).Value)
Next
mIdx=mIdx+1
Next
End Sub
End Module
$matches Array:
(
[0] => Array
(
[0] => word0 = word1, word.2 , word3.qrs_t-1
)
[1] => Array
(
[0] => word0
)
[2] => Array
(
[0] =>
)
[3] => Array
(
[0] => word1
)
[4] => Array
(
[0] =>
)
[5] => Array
(
[0] => word.2
)
[6] => Array
(
[0] =>
)
[7] => Array
(
[0] => word3.qrs_t-1
)
)
Related
I have a REGEX pattern I inherited that seems to work in online testers (demo here: https://regex101.com/r/KPpoLS/1)
However, it uses negative lookbehinds to avoid grabbing sub-stings of longer serial numbers. I need to use this REGEX pattern in a VBA macro to identify all the serials number patterns (listed below) - but VBA does not support negative lookbehinds from what I can tell.
Unfortunately, I'm not well versed enough in REGEX to re-engineer this REGEX pattern - can anyone offer any suggestions?
\b(?<!-)(\d\/[A-Z]{2}\/\d{6}-\d{2})|([A-Z]-\d\/[A-Z]{2}\/\d{6}-\d{2})|(?<![A-Z])([A-Z]\/[A-Z]{2}\/\d{6}-\d{2})|([A-Z]{2}\/[A-Z]{2}\/\d{6}-\d{2})|([A-Z][0-9]\/[A-Z]{2}\/\d{6}-\d{2})|(?<![A-Z])([A-Z]-[A-Z]{3}\/\d{6}-\d{2})|([0-9]\/[A-Z]{2}\/[A-Z]{3}\/\d{6}-\d{2})|([A-Z]\/[A-Z]{2}\/[A-Z]{3}\/\d{6}-\d{2})|([0-9]\/[A-Z]{2}\/[A-Z]{3}\/\d{4}-\d{2})|([0-9]\/[A-Z]{2}\/[A-Z]{3}\/\d{6}-\d{2})
[list arranged by sub-strings]
1/AA/111111-11
A-1/AA/111111-11
A/AA/111111-11
AA/AA/111111-11
A1/AA/111111-11
A-AAA/111111-11
1/AA/AAA/111111-11
A/AA/AAA/111111-11
1/AA/AAA/1111-11
[orginal list]
1/AA/111111-11
A/AA/111111-11
A1/AA/111111-11
AA/AA/111111-11
A-AAA/111111-11
1/AA/AAA/1111-11
A-1/AA/111111-11
1/AA/AAA/111111-11
A/AA/AAA/111111-11
Sub regex_test_by_word_story_ranges()
Dim stringone As String
Dim regexone As Object
Dim doc As Word.Document
Dim rng As Word.Range
Dim para As Word.Paragraph
Dim i as Long
Dim x As Long
Dim regcount As Long
Dim rngstory As Range
Dim serialArray() as String
Set regexone = New RegExp
Set doc = ActiveDocument
'=========================================
'Loop #1 to find Category 1 serial numbers
'=========================================
regexone.Pattern = ""
regexone.Global = True
regexone.Pattern = IgnoreCase
For Each rngstory in doc.StoryRanges
On Error Resume Next
rngstory.Select
stringone = stringone & rngstory.Text
Next rngstory
Set theMatches = regexone.Execute(stringone)
regcount = theMatches.Count
debug.print regcount
With theMatches
If .Count > 0 Then
ReDim Preserve serialArray(.Count, 5)
x = 1
For Each Match In theMatches
debug.print Match.value
serialArray(x, 1) = Match.value 'this will become a seach term for another macro
serialArray(x, 2) = Replace(Match.value, "/", "!") 'this will becom part of a URL
serialArray(x, 3) = "www.baseURL.com/" & Replace(Match.value, "/", "!") 'This is a base URL, which (X, 2) on the end. Search term from next macro will find and insert this hyperlink
serialArray(x, 4) = "Placeholder3" 'extra, will delete
serialArray(x, 5) = "Placeholder4" 'extra, will delete
x = x + 1
Next Match
End If
End With
'checking output of array:
For x = LBound(serialArray) To UBound(serialArray)
debug.print serialArray(x, 1) & ", " & serialArray(x, 2) & ", " & serialArray(x, 3) & ", " & serialArray(x, 4) & ", " & serialArray(x, 5)
Next x
'=========================================
'Loop #2 to find Category 2 serial numbers
'=========================================
'Same loop as above code, but I have not developed the REGEX for Category 2 serial numbers yet
'Loop #2 need add Matches from Loop #2 REGEX to the serialArray()
'This portion is beyond my original question, but would welcome any help on adding subsequent loop matches to the serialArray()
'https://stackoverflow.com/questions/60831517/alternative-to-negative-lookbehinds-in-vba-macro?noredirect=1#comment107630601_60831517
End Sub
When I try the following Regex code and add a "Add Watch" (Shift + F9) to Matches
Sub TestRegEx1()
Dim regex As Object, Matches As Object
Dim str As String
str = "This is text for the submatches"
Set regex = CreateObject("VBScript.RegExp")
regex.Pattern = "Th(is).+(for).+(submatches)|.+(\d)|([A-Z]{3})"
regex.IgnoreCase = True
Set Matches = regex.Execute(str)
End Sub
I see that Matches is structured like this (with 2 empty submatches):
2 questions:
How can I save in an array variable the SubMatches?
How can I Debug.Print only elements that are not empty?
I've tried doing like below but is not working
Set Arr = Matches.SubMatches
Set Arr = Matches(1).SubMatches
Set Arr = Matches.Item(1).SubMatches
Thanks in advance
Is the following what you intended? Oversize an array at the start and redim at the end. First version prints only non-empty but stores all. Second version prints and stores only non-empty.
You probably want to .Test to ensure there are matches.
Option Explicit
Sub TestRegEx1()
Dim regex As Object, matches As Object, match As Object, subMatch As Variant
Dim str As String, subMatches(), i As Long
ReDim subMatches(0 To 1000)
str = "This is text for the submatches"
Set regex = CreateObject("VBScript.RegExp")
regex.Pattern = "Th(is).+(for).+(submatches)|.+(\d)|([A-Z]{3})"
regex.IgnoreCase = True
Set matches = regex.Execute(str)
For Each match In matches
For Each subMatch In match.subMatches
subMatches(i) = match.subMatches(i)
If Not IsEmpty(subMatches(i)) Then Debug.Print subMatches(i)
i = i + 1
Next
Next
ReDim Preserve subMatches(0 To i)
End Sub
If you only want to store non-empty then
Option Explicit
Sub TestRegEx1()
Dim regex As Object, matches As Object, match As Object, subMatch As Variant
Dim str As String, subMatches(), i As Long
ReDim subMatches(0 To 1000)
str = "This is text for the submatches"
Set regex = CreateObject("VBScript.RegExp")
regex.Pattern = "Th(is).+(for).+(submatches)|.+(\d)|([A-Z]{3})"
regex.IgnoreCase = True
Set matches = regex.Execute(str)
For Each match In matches
For Each subMatch In match.subMatches
subMatches(i) = match.subMatches(i)
If Not IsEmpty(subMatches(i)) Then
Debug.Print subMatches(i)
i = i + 1
End If
Next
Next
ReDim Preserve subMatches(0 To i)
End Sub
You may use a Collection and fill it on the go.
Add
Dim m, coll As Collection
Initialize the collection:
Set coll = New Collection
Then, once you get the matches, use
If Matches.Count > 0 Then ' if there are matches
For Each m In Matches(0).SubMatches ' you need the first match submatches
If Len(m) > 0 Then coll.Add (m) ' if not 0 length, save value to collection
Next
End If
Result of the code with changes:
I'm trying to create a pattern for finding placeholders within a string to be able to replace them with variables later. I'm stuck on a problem to find all these placeholders within a string according to my requirement.
I already found this post, but it only helped a little:
Regex match ; but not \;
Placeholders will look like this
{&var} --> Variable stored in a dictionary --> dict("var")
{$prop} --> Property of a class cls.prop read by CallByName and PropGet
{#const} --> Some constant values by name from a function
Generally I have this pattern and it works well
Dim RegEx As Object
Set RegEx = CreateObject("VBScript.RegExp")
RegEx.pattern = "\{([#\$&])([\w\.]+)\}"
For example I have this string:
"Value of foo is '{&var}' and bar is '{$prop}'"
I get 2 matches as expected
(&)(var)
($)(prop)
I also want to add a formating part like in .Net to this expression.
String.Format("This is a date: {0:dd.mm.yyyy}", DateTime.Now());
// This is a date: 05.07.2019
String.Format("This is a date, too: {0:dd.(mm).yyyy}", DateTime.Now());
// This is a date, too: 05.(07).2019
I extended the RegEx to get that optional formatting string
Dim RegEx As Object
Set RegEx = CreateObject("VBScript.RegExp")
RegEx.pattern = "\{([#\$&])([\w\.]+):{0,1}([^\}]*)\}"
RegEx.Execute("Value of foo is '{&var:DD.MM.YYYY}' and bar is '{$prop}'")
I get 2 matches as expected
(&)(var)(DD.MM.YYYY)
($)(prop)()
At this point I noticed I have to take care for escapet "{" and "}", because maybe I want to have some brackets within the formattet result.
This does not work properly, because my pattern stops after "...{MM"
RegEx.Execute("Value of foo is '{&var:DD.{MM}.YYYY}' and bar is '{$prop}'")
It would be okay to add escape signs to the text before checking the regex:
RegEx.Execute("Value of foo is '{&var:DD.\{MM\}.YYYY}' and bar is '{$prop}'")
But how can I correctly add the negative lookbehind?
And second: How does this also works for variables, that should not be resolved, even if they have the correct syntax bus the outer bracket is escaped?
RegEx.Execute("This should not match '\{&var:DD.\{MM\}.YYYY\}' but this one '{&var:DD.\{MM\}.YYYY}'")
I hope my question is not confusing and someone can help me
Update 05.07.19 at 12:50
After the great help of #wiktor-stribiżew the result is completed.
As requested i provide some example code:
Sub testRegEx()
Debug.Print FillVariablesInText(Nothing, "Date\\\\{$var01:DD.\{MM\}.YYYY}\\\\ Var:\{$nomatch\}{$var02} Double: {#const}{$var01} rest of string")
End Sub
Function FillVariablesInText(ByRef dict As Dictionary, ByVal txt As String) As String
Const c_varPattern As String = "(?:(?:^|[^\\\n])(?:\\{2})*)\{([#&\$])([\w.]+)(?:\:([^}\\]*(?:\\.[^\}\\]*)*))?(?=\})"
Dim part As String
Dim snippets As New Collection
Dim allMatches, m
Dim i As Long, j As Long, x As Long, n As Long
' Create a RegEx object and execute pattern
Dim RegEx As Object
Set RegEx = CreateObject("VBScript.RegExp")
RegEx.pattern = c_varPattern
RegEx.MultiLine = True
RegEx.Global = True
Set allMatches = RegEx.Execute(txt)
' Start at position 1 of txt
j = 1
n = 0
For Each m In allMatches
n = n + 1
Debug.Print "(" & n & "):" & m.value
Debug.Print " [0] = " & m.SubMatches(0) ' Type [&$#]
Debug.Print " [1] = " & m.SubMatches(1) ' Name
Debug.Print " [2] = " & m.SubMatches(2) ' Format
part = "{" & m.SubMatches(0)
' Get offset for pre-match-string
x = 1 ' Index to Postion at least +1
Do While Mid(m.value, x, 2) <> part
x = x + 1
Loop
' Postition in txt
i = m.FirstIndex + x
' Anything to add to result?
If i <> j Then
snippets.Add Mid(txt, j, i - j)
End If
' Next start postition (not Index!) + 1 for lookahead-positive "}"
j = m.FirstIndex + m.Length + 2
' Here comes a function get a actual value
' e.g.: snippets.Add dict(m.SubMatches(1))
' or : snippets.Add Format(dict(m.SubMatches(1)), m.SubMatches(2))
snippets.Add "<<" & m.SubMatches(0) & m.SubMatches(1) & ">>"
Next m
' Any text at the end?
If j < Len(txt) Then
snippets.Add Mid(txt, j)
End If
' Join snippets
For i = 1 To snippets.Count
FillVariablesInText = FillVariablesInText & snippets(i)
Next
End Function
The function testRegEx gives me this result and debug print:
(1):e\\\\{$var01:DD.\{MM\}.YYYY(2):}{$var02
[0] = $
[1] = var02
[2] =
(1):e\\\\{$var01:DD.\{MM\}.YYYY
[0] = $
[1] = var01
[2] = DD.\{MM\}.YYYY
(2):}{$var02
[0] = $
[1] = var02
[2] =
(3): {#const
[0] = #
[1] = const
[2] =
(4):}{$var01
[0] = $
[1] = var01
[2] =
Date\\\\<<$var01>>\\\\ Var:\{$nomatch\}<<$var02>> Double: <<#const>><<$var01>> rest of string
You may use
((?:^|[^\\])(?:\\{2})*)\{([#$&])([\w.]+)(?::([^}\\]*(?:\\.[^}\\]*)*))?}
To make sure the consecutive matches are found, too, turn the last } into a lookahead, and when extracting matches just append it to the result, or if you need the indices increment the match length by 1:
((?:^|[^\\])(?:\\{2})*)\{([#$&])([\w.]+)(?::([^}\\]*(?:\\.[^}\\]*)*))?(?=})
^^^^^
See the regex demo and regex demo #2.
Details
((?:^|[^\\])(?:\\{2})*) - Group 1 (makes sure the { that comes next is not escaped): start of string or any char but \ followed with 0 or more double backslashes
\{ - a { char
([#$&]) - Group 2: any of the three chars
([\w.]+) - Group 3: 1 or more word or dot chars
(?::([^}\\]*(?:\\.[^}\\]*)*))? - an optional sequence of : and then Group 4:
[^}\\]* - 0 or more chars other than } and \
(?:\\.[^}\\]*)* - zero or more reptitions of a \-escaped char and then 0 or more chars other than } and \
} - a } char
Welcome to the site! If you need to only match balanced escapes, you will need something more powerful. If not --- I haven't tested this, but you could try replacing [^\}]* with [^\{\}]|\\\{|\\\}. That is, match non-braces and escaped brace sequences separately. You may need to change this depending on how you want to handle backslashes in your formatting string.
I have a field data extracted from a database which represents a range of values, but it's coming in Excel as a String format $86,000 - $162,000.
I need to extract the minimum value and the maximum value from each cell, so I need to extract the numeric portion of it, and ignore the $, - and the ,.
I've attached an image of the data I have, and the values I want to extract from it.
This is the closest pattern I got with RegEx, but I'ts not what I'm looking for.
Pattern = (\d+)(?:\.(\d{1,2}))?
Can anyone assist ?
Just wondering why Regex?
Function GetParts(priceRange As String) As Double()
Dim arr() As String
Dim parts() As Double
If InStr(1, priceRange, "-") > 0 Then
arr = Split(priceRange, "-")
ReDim parts(0 To UBound(arr))
Dim i As Long
For i = 0 To UBound(arr)
parts(i) = CDbl(Replace$(Replace$(Trim$(arr(i)), "$", ""), ",", ""))
Next i
End If
GetParts = parts
End Function
Sub test()
MsgBox GetParts("$14,000 - $1,234,567")(0) 'Minimum
End Sub
EDIT
Yet you could do this with regex to match the data string into the parts:
Function GetPartsRegEx(priceRange As String) As Variant
Dim arr() As Double
Dim pricePattern As String
pricePattern = "(\$?\d+[\,\.\d]*)"
'START EDIT
Static re As RegExp
If re Is Nothing Then
Set re = New RegExp
re.IgnoreCase = True
re.Global = True
re.Pattern = pricePattern & "\s*[\-]\s*" & pricePattern 'look for the pattern first
End If
Static nums As RegExp
If nums Is Nothing Then
Set nums = New RegExp
'to remove all non digits, except decimal point in case you have pennies
nums.Pattern = "[^0-9.]"
nums.Global = True
End If
'END EDIT
If re.test(priceRange) Then
ReDim arr(0 To 1) ' fill return array
arr(0) = CDbl(nums.Replace(re.Replace(priceRange, "$1"), ""))
arr(1) = CDbl(nums.Replace(re.Replace(priceRange, "$2"), ""))
Else
'do some error handling here
Exit Function
End If 'maybe throw error if no +ve test or
GetPartsRegEx = arr
End Function
Sub test()
MsgBox GetPartsRegEx("$1,005.45 - $1,234,567.88")(1)
End Sub
Here is quick Example Demo https://regex101.com/r/RTNlVF/1
Pattern "^\$(\d+\,\d+)\s\-\s\$(\d+\,\d+)"
Option Explicit
Private Sub Example()
Dim RegExp As New RegExp
Dim Pattern As String
Dim CelValue As String
Dim rng As Range
Dim Cel As Range
Set rng = ActiveWorkbook.Sheets("Sheet1" _
).Range("A2", Range("A9999" _
).End(xlUp))
For Each Cel In rng
DoEvents
Pattern = "^\$(\d+\,\d+)\s\-\s\$(\d+\,\d+)"
If Pattern <> "" Then
With RegExp
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = Pattern
End With
If RegExp.Test(Cel.Value) Then
' Debug.Print Cel.Value
Debug.Print RegExp.Replace(CStr(Cel), "$1")
Debug.Print RegExp.Replace(CStr(Cel), "$2")
End If
End If
Next
End Sub
Without a loop (but still no regex):
Sub Split()
With Columns("B:B")
.Replace What:="$", Replacement:=""
Application.CutCopyMode = False
.TextToColumns Destination:=Range("B1"), DataType:=xlDelimited, Other:=True, OtherChar:="-", FieldInfo:=Array(Array(1, 1), Array(2, 1))
End With
Columns("B:C").Insert Shift:=xlToRight
Columns("D:E").NumberFormat = "0"
Range("D1").FormulaR1C1 = "Min Value"
Range("E1").FormulaR1C1 = "Max Value"
With Range("D1:E1").Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 12611584
End With
With Range("D1:E1").Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
End Sub
I made this function:
Hope it helps.
Code:
Function ExtractNumber(ByVal TextInput As String, _
Optional ByVal Position As Byte = 0, _
Optional ByVal Delimiter As String = "-") As Variant
' You can use this function in a subprocess that
' writes the values in the cells you want, or
' you can use it directly in the ouput cells
' Variables
Dim RemoveItems(2) As String
Dim Aux As Variant
' The variable RemoveItems is an array
' containing the characters you want to remove
RemoveItems(0) = "."
RemoveItems(1) = ","
RemoveItems(2) = " "
' STEP 1 - The variable Aux will store the text
' given as input
Aux = TextInput
' STEP 2 - Characters stored in the variable
' RemoveItems will be removed from Aux
For i = 0 To UBound(RemoveItems)
Aux = Replace(Aux, RemoveItems(i), "")
Next i
' STEP 3 - Once Aux is "clean", it will be
' transformed into an array containing the
' values separated by the delimiter
' As you can see at the function's header,
' Delimiter default value is "-". You can change
' it depending on the situation
Aux = Split(Aux, Delimiter)
' STEP 4 - The result of this function will be
' a numeric value. So, if the value of the
' selected position in Aux is not numeric it will
' remove the first character assuming it is a
' currency symbol.
' If something fails in the process the function
' will return "ERROR", so you can know you may
' verify the inputs or adjust this code for
' your needs.
On Error GoTo ErrHndl
If Not IsNumeric(Aux(Position)) Then
ExtractNumber = CLng(Mid(Aux(Position), 2))
Else
ExtractNumber = CLng(Aux(Position))
End If
Exit Function
ErrHndl:
ExtractNumber = "ERROR"
End Function
You can even do this with just worksheet formulas. Under certain circumstances, Excel will ignore the $ and ,. The double unary converts the returned string to a numeric value.
First Value: =--LEFT(A1,FIND("-",A1)-1)
Second Value: =--MID(A1,FIND("-",A1)+1,99)
Here is my regex: {{[^\{\s}]+\}}
And my input is {{test1}}{{test2}}{{test3}}.
How can I get these 3 tests by array using regex expression?
I would use: ~\{\{([^}]+?)\}\}~
and accessing array depends on your language!
[EDIT] add explanations
~: delimiter
\{\{, \}\}~: match characters literally. Should be
escaped.
[^}]: match anything inside {{}} until a }
+: repeat
pattern multiple times (for multiple characters)
?: is for 'lazy'
to match as few times as possible.
(): is to capture
:)
[EDIT] add PHP code sample for matching illustration:
<?php
$string= "{{test1}}{{test2}}{{test3}}";
if (preg_match_all("~\{\{([^}]+?)\}\}~s", $string, $matches))
{
print_r(array($matches));
// Do what you want
}
?>
will output this:
Array
(
[0] => Array
(
[0] => Array
(
[0] => {{test1}}
[1] => {{test2}}
[2] => {{test3}}
)
[1] => Array
(
[0] => test1
[1] => test2
[2] => test3
)
)
)
test[0-9]+
This matches all occurences of testX where X is an integer of any size.
If you're trying to identify the braces instead, use this:
[{\}]
C# uses Matches Method returns MatchCollection object.
Here is some codes,
Regex r = new Regex(#"{{[^{\s}]+}}");
MatchCollection col = r.Matches("{{test1}}{{test2}}{{test3}}");
string[] arr = null;
if (col != null)
{
arr = new string[col.Count];
for (int i = 0; i < col.Count; i++)
{
arr[i] = col[i].Value;
}
}