What is the better Regex Expression

Viewed 68

In my program, I convert an invoice pdf to text. I am looking for a better Regex Expression to parse the string. The results of my conversion are a very long string:

This is a very long string. Invoice Total: $1,399.52 Continuation of very long string.

I want to parse out the 1399.52 Following the "Invoice Total:".

Here is my first attempt:

    Dim text As String = "This is a very long string. Invoice Total: $1,399.52 Continuation of very long string."
    Dim re As Regex = New Regex("Invoice Total:\s*\$((\d|\.)*)")
    Dim m As Match = re.Match(text)
    For groupIdx As Integer = 0 To m.Groups.Count - 1
        Console.WriteLine("[{0}] = {1}", re.GetGroupNames(groupIdx), m.Groups(groupIdx).Value)

        If(groupIdx = 1) Then
            txtTotal.Text =  m.Groups(groupIdx).Value
        End If
    Next


Matches Found:
[0][0] = Invoice Total: $1,399.52
[0][1] = 1399.52
[0][2] = 0

The code works, but I know there is a better way.

1 Answers

You can use

Dim text As String = "This is a very long string. Invoice Total: $1,399.52 Continuation of very long string."
Dim re As Regex = New Regex("Invoice Total:\s*\$(\d+(?:,\d+)*(?:\.\d+)?)")
Dim m As Match = re.Match(text)
If m.Success Then
    Console.WriteLine(m.Groups(1).Value.Replace(",",""))
End If

See the VB.NET demo and the .NET regex demo.

NOTE: The regex can be simplified depending on the real life context. If the number ends with the first whitespace, you can use a mere

Invoice Total:\s*\$(\S+)

where \S+ will match one or more non-whitespace chars. Regex detail:

  • Invoice Total: - a literal string (used as left-hand side context)
  • \s* - zero or more whitespaces
  • \$ - a $ char
  • (\d+(?:,\d+)*(?:\.\d+)?) - Capturing group 1:
    • \d+ - one or more digits
    • (?:,\d+)* - zero or more repetitions of a comma and one or more digits
    • (?:\.\d+)? - an optional occurrence of a period and one or more digits.

Note that the commas can be removed with a mere .Replace(",",""), or you may cast the extract number to a decimal as shown by Jimi. Note you cannot extract the number without commas into Group 1 because regex parses the string continuously from left to right, and cannot skip chars when writing the (sub)match value into a group.

Related