user8375562874527
user8375562874527

Reputation: 68

Replace string to the target format

Is there a way to replace a string using regex or string replace

COND X > 49 300000 200000

The expected format is

COND(X > 49,300000,200000)

My current approach is to do string.Split(" ") and convert it to list and insert the braces at the proper indexes. But the problem with my approach is the string is not standalone but is included in a larger expression and also sometimes the comparison happens with whitespace as in COND ABC =. The right side of the condition is a whitespace.

Upvotes: 2

Views: 94

Answers (3)

Kasravnd
Kasravnd

Reputation: 107287

You can use following regex for detect :

(.*)(\w\s?>[\s\d]+)

and following for replace :

$1\($2\)

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626748

It is impossible to achieve in a single pass. I suggest:

  1. Adding parentheses: (\p{Lu}+)\s*(\p{Lu}+)(.*) (replace with $1($2$3))

See demo

  1. Then, you can use a regex to find all spaces between numbers and replace them with a comma: (?<=\d+)\s+(?=\d+).

See demo (see Context tab).

Here is a working VB.NET code:

Dim strIn As String = "COND X > 49 300000 200000"
Dim rx2 = New Regex("(\p{Lu}+)\s*(\p{Lu}+)(.*)")
Dim result2 As String = rx2.Replace(strIn, "$1($2$3)")
result2 = Regex.Replace(result2, "(?<=\d+)\s+(?=\d+)", ",")

Output:

enter image description here

EDIT: 1-REGEX PASS:

If you use a MatchEvaluator function inside Regex.Replace, we can make sure we only run regex once.

Dim str3 = "COND X > 49 300000 200000 778888"
    Dim rx3 = New Regex("(\p{Lu}+)\s*(\p{Lu}+.*?)(?:\s+(\d+))+")
    Dim result2 = rx3.Replace(str3, New MatchEvaluator(Function(m As Match)
                        If m.Groups(3).Captures.Count > 0 Then
                             Return String.Format("{0}({1} {2})",
                                               m.Groups(1).Value,
                                               m.Groups(2).Value,
                                               String.Join(",",
                                                            m.Groups(3).Captures.Cast(Of Capture)().Select(Function(n) n.Value).ToArray()
                                                           )
                                               )
                         Else
                             Return m.Value
                         End If
                         End Function))

Result:

enter image description here

Upvotes: 2

Shar1er80
Shar1er80

Reputation: 9041

Setup your capture groups in your RegularExpression and just stick the appropriate delimiters between the groups.

NOTE: This only works if you have 3 sets of digits you want to stick commas in between.

Imports System
Imports System.Text.RegularExpressions

Module Module1
    Sub Main()
        Dim str As String = "COND X < 49 300000 200000"
        '^ Beginning of the line
        '([A-Z]+)\s* capture group 1 that will have any capital letters before the first space,
        '  but the space is not included in the group
        '([A-Z]\s*..?\s*) capture group 2 that will have X (or any single capital letter) plus
        '  a space, then any character plus a possible character (<=), then a space
        '(\d+)\s* capture group 3 & 4 that will have the first group of digits plus a space, but 
        '  the space is not included in the group
        '(\d+)$ capture group 5 that will have the last group of digits. $ End of line
        Dim pattern As String = "^([A-Z]+)\s*([A-Z]\s*..?\s*)(\d+)\s*(\d+)\s*(\d+)$"
        Console.WriteLine(Regex.Replace(str, pattern, "$1($2$3,$4,$5)"))
        Console.ReadLine()
    End Sub
End Module

Results:

COND(X > 49,300000,200000)

UPDATE

If you're dealing with more than three sets of digits, then using Regex.Match and building your string allows one pass through.

Imports System
Imports System.Text.RegularExpressions

Module Module1
    Sub Main()
        Dim str As String = "COND X >= 49 300000 200000 123456 456789"
        '([A-Z]+)\s* capture group 1 that will have any capital letters before the first space,
        '  but the space is not included in the group
        '([A-Z]\s*..?\s*) capture group 2 that will have X (or any single capital letter) plus
        '  a space, then any character plus a possible character (<=), then a space
        '(.+)\s* capture group 3 that will have the sets of digits with spaces in between
        Dim pattern As String = "([A-Z]+)\s*([A-Z]\s*..?\s*)(.+)"
        Dim groups As GroupCollection = Regex.Match(str, pattern).Groups
        Console.WriteLine("{0}({1}{2})", groups(1), groups(2), groups(3).Value.Replace(" ", ","))
        Console.ReadLine()
    End Sub
End Module

Results:

COND(X >= 49,300000,200000,123456,456789)

Upvotes: 2

Related Questions