Regex questions

J

Just Me

I want to use regular expressions to search a string, give the user the
option of replacing, and then maybe replacing the data - using reg
expressions for the search and the replace strings.

However all the Regex replace methods seem to combine in one call the search
and replace.

Is there a way of doing what I want?



Thanks
 
S

Samu Lang

The replace methods [1] do combine the search and replace functionality in
one call.
However, you can use the overloads [2] that take a MatchEvaluator [3]
parameter to pass a reference to a function of yours to be called on each
match [4].
Alternatively you could iterate the matches [5] and use the index [6] and
length [7] properties to act on the original string.

[1]
http://msdn.microsoft.com/library/d...tRegularExpressionsRegexClassReplaceTopic.asp
[2]
http://msdn.microsoft.com/library/d...RegularExpressionsRegexClassReplaceTopic1.asp
[3]
http://msdn.microsoft.com/library/d...egularexpressionsmatchevaluatorclasstopic.asp
[4]
http://msdn.microsoft.com/library/d...stemtextregularexpressionsmatchclasstopic.asp
[5]
http://msdn.microsoft.com/library/d...tRegularExpressionsRegexClassMatchesTopic.asp
[6]
http://msdn.microsoft.com/library/d...tregularexpressionscaptureclassindextopic.asp
[7]
http://msdn.microsoft.com/library/d...regularexpressionscaptureclasslengthtopic.asp
 
J

Just Me

Alternatively you could iterate the matches [5] and use the index [6] and
length [7] properties to act on the original string.
This is what I do now. However, I simply replace the found string with a
replace string.
That is, I do not allow the regular expression type replacements using
groups of characters found in the search. That's what I can't find out how
to do.

Thanks
 
J

Just Me

I read your references and need to read them again.
For example, I find the following confusing:
Substitutions are allowed only within replacement patterns. For similar
functionality within regular expressions, use a backreference

Is the term Regular expression only used for the "Find" pattern?

I have been having problems with grouping.
Read the Help I sometimes see something like (\W+) and sometimes {:a+}
I've used the braces in the IDE editor with \1 and that works.

I tried it in my Regex and it doesn't seem to work.
Should it work in Regex?

When is prentices used "(\W+)" and what is the reference construct that
goes with it.

When is $1 used?

Thanks a lot for sticking with me

PS I have the search - ask - replace working.
I search, ask and then replace using the found characters as the string to
search. That is, to replace, I let replace search the string previously
found and then do the replacement.
 
J

Jay B. Harlow [MVP - Outlook]

Just Me,
I don't believe the RegEx library provides that functionality per se.

It sounds like you want a Replace method on the Match object itself.

If you do, what I would consider doing is do the RegEx.Replace on
Match.Value, (Match.Value is inherited from Capture). It should be the
"entire" string that was found. Where I append the value returned from
RegEx.Replace to a StringBuilder... The trick is going to be, how to collect
the "non-matched parts of the original string... You might be able to
extrapolate these parts from Match.Index & Match.Length.

Something like:

Const pattern As String = "(?<key>\w+)=(?<value>\w+):);|)"
Const replacement As String = "The ${key} has value ${value}"

Dim input As String = "a=1;b=2;c=3;d=4;e=5;"

Dim parser As Regex = New Regex(pattern, RegexOptions.Compiled)

Dim match As Match = parser.Match(input)

Dim output As New System.Text.StringBuilder
Dim startIndex As Integer = 0

Debug.WriteLine(input, "input")

Do While match.Success
'Debug.WriteLine(match.Groups("key"), "key")
'Debug.WriteLine(match.Groups("value"), "value")

output.Append(input.Substring(startIndex, match.Index -
startIndex))
output.Append(parser.Replace(match.Value, replacement))

startIndex = match.Index + match.Length

match = match.NextMatch()
Loop

Debug.WriteLine(output.ToString(), "output")

Of course the above loop would be "better" with a MatchEvaluator, however
hopefully it gives you enough to do "un-roll" the loop & what you are
wanting... such as calling the Replace function based on a button click!

Hope this helps
Jay



Just Me said:
Alternatively you could iterate the matches [5] and use the index [6] and
length [7] properties to act on the original string.
This is what I do now. However, I simply replace the found string with a
replace string.
That is, I do not allow the regular expression type replacements using
groups of characters found in the search. That's what I can't find out how
to do.

Thanks
 
J

Jay B. Harlow [MVP - Outlook]

Just Me,
Here is a quick Find & Replace class based on my other sample:

Public Class FindReplace

Private m_parser As Regex
Private m_replacement As String
Private m_input As String
Private m_output As StringBuilder
Private m_startIndex As Integer
Private m_match As Match

Public Property Pattern() As String
Get
Return m_parser.ToString()
End Get
Set(ByVal value As String)
m_parser = New Regex(value, RegexOptions.Compiled)
End Set
End Property

Public Property Replacement() As String
Get
Return m_replacement
End Get
Set(ByVal value As String)
m_replacement = value
End Set
End Property

Public Property Input() As String
Get
Return m_input
End Get
Set(ByVal value As String)
m_input = value
m_output = New StringBuilder
m_startIndex = 0
End Set
End Property

Public ReadOnly Property Output() As String
Get
Return m_output.ToString()
End Get
End Property

Public Function FindNext() As Boolean
If m_match Is Nothing Then
m_match = m_parser.Match(m_input)
Else
m_match = m_match.NextMatch()
End If
Return m_match.Success
End Function

Public Function Replace() As Boolean
If Not m_match.Success Then
FindNext()
End If
If m_match.Success Then
m_output.Append(m_input, m_startIndex, m_match.Index -
m_startIndex)
m_output.Append(m_parser.Replace(m_match.Value,
m_replacement))
m_startIndex = m_match.Index + m_match.Length
End If
Return m_match.Success
End Function

Public Overrides Function ToString() As String
Return m_output.ToString()
End Function

End Class

Public Sub Main()
Dim find As New FindReplace
find.Pattern = "(?<key>\w+)=(?<value>\w+):);|)"
find.Replacement = "Key ${key} has value ${value}"
find.Input = "a=1;b=2;c=3;d=4;e=5;"

Do While find.Replace()

Loop
Debug.WriteLine(find.ToString(), "output")

End Sub

Alternate loop that should also work:

Do While find.FindNext()
find.Replace()
Loop

Hope this helps
Jay

Just Me said:
Alternatively you could iterate the matches [5] and use the index [6] and
length [7] properties to act on the original string.
This is what I do now. However, I simply replace the found string with a
replace string.
That is, I do not allow the regular expression type replacements using
groups of characters found in the search. That's what I can't find out how
to do.

Thanks
 
J

Jay B. Harlow [MVP - Outlook]

Doh!

The Replace function had a bug in it, here is a replacement:

Public Function Replace() As Boolean
If (m_match Is Nothing) _
OrElse (Not m_match.Success) _
OrElse (m_startIndex > m_match.Index) Then
FindNext()
End If
If m_match.Success Then
m_output.Append(m_input, m_startIndex, m_match.Index -
m_startIndex)
m_output.Append(m_parser.Replace(m_match.Value,
m_replacement))
m_startIndex = m_match.Index + m_match.Length
End If
Return m_match.Success
End Function

The above Replace will enable the following to work as expected:

Do While Replace()
' This space intentionally left blank.
Loop

Jay



Jay B. Harlow said:
Just Me,
Here is a quick Find & Replace class based on my other sample:

Public Class FindReplace

Private m_parser As Regex
Private m_replacement As String
Private m_input As String
Private m_output As StringBuilder
Private m_startIndex As Integer
Private m_match As Match

Public Property Pattern() As String
Get
Return m_parser.ToString()
End Get
Set(ByVal value As String)
m_parser = New Regex(value, RegexOptions.Compiled)
End Set
End Property

Public Property Replacement() As String
Get
Return m_replacement
End Get
Set(ByVal value As String)
m_replacement = value
End Set
End Property

Public Property Input() As String
Get
Return m_input
End Get
Set(ByVal value As String)
m_input = value
m_output = New StringBuilder
m_startIndex = 0
End Set
End Property

Public ReadOnly Property Output() As String
Get
Return m_output.ToString()
End Get
End Property

Public Function FindNext() As Boolean
If m_match Is Nothing Then
m_match = m_parser.Match(m_input)
Else
m_match = m_match.NextMatch()
End If
Return m_match.Success
End Function

Public Function Replace() As Boolean
If Not m_match.Success Then
FindNext()
End If
If m_match.Success Then
m_output.Append(m_input, m_startIndex, m_match.Index -
m_startIndex)
m_output.Append(m_parser.Replace(m_match.Value,
m_replacement))
m_startIndex = m_match.Index + m_match.Length
End If
Return m_match.Success
End Function

Public Overrides Function ToString() As String
Return m_output.ToString()
End Function

End Class

Public Sub Main()
Dim find As New FindReplace
find.Pattern = "(?<key>\w+)=(?<value>\w+):);|)"
find.Replacement = "Key ${key} has value ${value}"
find.Input = "a=1;b=2;c=3;d=4;e=5;"

Do While find.Replace()

Loop
Debug.WriteLine(find.ToString(), "output")

End Sub

Alternate loop that should also work:

Do While find.FindNext()
find.Replace()
Loop

Hope this helps
Jay

Just Me said:
Alternatively you could iterate the matches [5] and use the index [6]
and length [7] properties to act on the original string.
This is what I do now. However, I simply replace the found string with a
replace string.
That is, I do not allow the regular expression type replacements using
groups of characters found in the search. That's what I can't find out
how to do.

Thanks
 
J

Just Me

Wow - I'm going to go off-line and study this.

Thanks



Jay B. Harlow said:
Doh!

The Replace function had a bug in it, here is a replacement:

Public Function Replace() As Boolean
If (m_match Is Nothing) _
OrElse (Not m_match.Success) _
OrElse (m_startIndex > m_match.Index) Then
FindNext()
End If
If m_match.Success Then
m_output.Append(m_input, m_startIndex, m_match.Index -
m_startIndex)
m_output.Append(m_parser.Replace(m_match.Value,
m_replacement))
m_startIndex = m_match.Index + m_match.Length
End If
Return m_match.Success
End Function

The above Replace will enable the following to work as expected:

Do While Replace()
' This space intentionally left blank.
Loop

Jay



Jay B. Harlow said:
Just Me,
Here is a quick Find & Replace class based on my other sample:

Public Class FindReplace

Private m_parser As Regex
Private m_replacement As String
Private m_input As String
Private m_output As StringBuilder
Private m_startIndex As Integer
Private m_match As Match

Public Property Pattern() As String
Get
Return m_parser.ToString()
End Get
Set(ByVal value As String)
m_parser = New Regex(value, RegexOptions.Compiled)
End Set
End Property

Public Property Replacement() As String
Get
Return m_replacement
End Get
Set(ByVal value As String)
m_replacement = value
End Set
End Property

Public Property Input() As String
Get
Return m_input
End Get
Set(ByVal value As String)
m_input = value
m_output = New StringBuilder
m_startIndex = 0
End Set
End Property

Public ReadOnly Property Output() As String
Get
Return m_output.ToString()
End Get
End Property

Public Function FindNext() As Boolean
If m_match Is Nothing Then
m_match = m_parser.Match(m_input)
Else
m_match = m_match.NextMatch()
End If
Return m_match.Success
End Function

Public Function Replace() As Boolean
If Not m_match.Success Then
FindNext()
End If
If m_match.Success Then
m_output.Append(m_input, m_startIndex, m_match.Index -
m_startIndex)
m_output.Append(m_parser.Replace(m_match.Value,
m_replacement))
m_startIndex = m_match.Index + m_match.Length
End If
Return m_match.Success
End Function

Public Overrides Function ToString() As String
Return m_output.ToString()
End Function

End Class

Public Sub Main()
Dim find As New FindReplace
find.Pattern = "(?<key>\w+)=(?<value>\w+):);|)"
find.Replacement = "Key ${key} has value ${value}"
find.Input = "a=1;b=2;c=3;d=4;e=5;"

Do While find.Replace()

Loop
Debug.WriteLine(find.ToString(), "output")

End Sub

Alternate loop that should also work:

Do While find.FindNext()
find.Replace()
Loop

Hope this helps
Jay

Just Me said:
Alternatively you could iterate the matches [5] and use the index [6]
and length [7] properties to act on the original string.

This is what I do now. However, I simply replace the found string with a
replace string.
That is, I do not allow the regular expression type replacements using
groups of characters found in the search. That's what I can't find out
how to do.

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top