tags:

views:

68

answers:

2

My coworker needs me to write him a regular expression for his vb.net app.

I do not know vb and he does not know regex.

The regex he needs is:

/.*web id: ?(\d+).*/i

Basically he needs to search a string for something like "web id: 345" or "web id:2534" and retrieve the ID.

He took what I gave him above and was able to put this together:

Dim strPattern As String = ".*web id: ?(\d+).*"
Dim strReplacement$ = "$1"

GetWebId$ = Regex.Replace(LCase$(strNote$), strPattern$, strReplacement$)

However I am not sure how you pass the case-insensitive flag? (his current fix for that is making the whole string lowercase first)

Also one thing I can't seem to figure out is when he runs this on a string with multiple lines, any text that is not on the same line as "web id: \d" is also being returned which i find strange.

+3  A: 

Use the RegexOptions.IgnoreCase flag:

Regex.Replace(strNote, strPattern, strReplacement, RegexOptions.IgnoreCase)

If you are going to ignore case there should be no need to use LCase. I also find it odd that you have all those $ symbols in your variable names - they shouldn't be valid in either C# or VB.NET.


EDIT #2: I realize you may have wanted to replace the entire line that matched with the $1 replacement pattern to match the ID. If you have a need to use multiple options you can Or them together as follows:

Regex.Replace(input, pattern, replacement, RegexOptions.IgnoreCase Or RegexOptions.Singleline)

EDIT #1: you are using the wrong method to extract the ID. You have a group (\d+) to capture the ID, but you are using Regex.Replace on your match, which is why you get everything else in the text. To match the ID use the following:

Dim input As String = "foo web id:2010 bar"
Dim pattern As String = ".*web id: ?(\d+).*"
Dim m As Match = Regex.Match(input, pattern, RegexOptions.IgnoreCase)

If m.Success Then
    Dim id As String = m.Groups(1).Value
    Console.WriteLine("ID: " & id)
Else
    Console.WriteLine("No Match!")
End If

You will notice we refer to Groups(1) which holds the value captured by the (\d+) group. Patterns with more groups may lead to confusion, especially with nested groups. In those cases you can use named groups. Here is the same code updated to use named groups:

Dim input As String = "foo web id:2010 bar"
Dim pattern As String = ".*web id: ?(?<ID>\d+).*" ' group name added '
Dim m As Match = Regex.Match(input, pattern, RegexOptions.IgnoreCase)

If m.Success Then
    ' refer to group by group name '
    Dim id As String = m.Groups("ID").Value
    Console.WriteLine("ID: " & id)
Else
    Console.WriteLine("No Match!")
End If
Ahmad Mageed
Thanks, my bigger issue though was when running this on multi-line text.
John Isaacks
@John see my updates. If you still have issues please updated your post with some sample input with "multi-line" text.
Ahmad Mageed
That does exactly what he wanted, thanks!
John Isaacks
@John great! I also added another edit to show how to combine multiple options.
Ahmad Mageed
+1  A: 

Kind of unrelated, but this code is a collection of things you shouldn’t do in VB.NET.

You shouldn’t use the old $ suffix on string variables, and likewise you shouldn’t use old functions such as LCase$. There are equivalent functions in the framework that should be used. You can also tell your friend to always enable Option Strict while where at it. This will catch a lot of potential bugs.

Furthermore, to set the return value of a function, the … “more established” method is to use Return …, not Functionname = ….

So the “correct” code will look like this:

''// I’m assuming that `GetWebId` is the name of the function we’re in.
Function GetWebId(note As String) As String
    Dim pattern As String = ".*web id: ?(\d+).*"
    Dim replacement As String = "$1"
    Return Regex.Replace(note.ToLower(), pattern, replacement)
End Function

See Ahmad’s solution of how to get the “ignorecase” flag into the expression.

Konrad Rudolph
Thanks, I found out to handle the multi-line issue he was having he needed to include the flag, `RegexOptions.Singline`. Is there a way he can pass 2 options?
John Isaacks