2

Right now I have a couple separate regular expressions to filter data from a string but I'm curious if there's a way to do it all in one go.

Sample Data: (DATA$0$34.0002,5.3114$34.0002,5.2925$34.0004,5.3214$34.0007,2.2527$34.0002,44.3604$34.0002,43.689$34.0004,38.3179$34.0007,8.1299)

  1. Need to verify there's an open and close parentheses ( )
  2. Need to verify there's a "DATA$0" after the open parenthesis
  3. Need to split the results by $
  4. Need to split that subset by comma
  5. Need to capture only the last item of that subset (i.e. 5.3114, 5.2925, 5.3214, etc.)

My first check is on parenthesis using (([^)]+)) as my RegEx w/ RightToLeft & ExplicitCapture options (some lines can have multiple data sets).

Next I filter for the DATA$0 using (?:(DATA$0)

Finally I do my splits and take the last value in the array to get what I need but I'm trying to figure out if there's a better way.

string DataPattern = @"(?:\(DATA\$0)";
string ParenthesisPattern = @"\(([^)]+)\)";
RegexOptions options = RegexOptions.RightToLeft | RegexOptions.ExplicitCapture;

StreamReader sr = new StreamReader(FilePath);
while (!sr.EndOfStream)
{
    string line = sr.ReadLine();
    Console.WriteLine(line);

    Match parentMatch = Regex.Match(line, ParenthesisPattern, options);
    if (parentMatch.Success)
    {
        string value = parentMatch.Value;

        Match dataMatch = Regex.Match(value, DataPattern);
        if (dataMatch.Success)
        {
            string output = parentMatch.Value.Replace("(DATA$0", "").Replace(")", "");
            string[] splitOutput = Regex.Split(output, @"\$");

            foreach (string x in splitOutput)
            {
                if (!string.IsNullOrEmpty(x))
                {
                    string[] splitDollar = Regex.Split(x, ",");
                    if (splitDollar.Length > 0)
                        Console.WriteLine("Value: " + splitDollar[splitDollar.Length - 1]);
                }
            }
        }
        else
            Console.WriteLine("NO DATA");
    }
    else
        Console.WriteLine("NO PARENTHESIS");

    Console.ReadLine();
}

TIA

1 Answer 1

1

You can use

var results = Regex.Matches(text, @"(?<=\(DATA\$0[^()]*,)[^(),$]+(?=(?:\$[^()]*)?\))")
    .Cast<Match>()
    .Select(x => x.Value)
    .ToList();

See the regex demo. Details:

  • (?<=\(DATA\$0[^()]*,) - a positive lookbehind that matches a location that is immediately preceded with (DATA$0, zero or more chars other than ( and ) (as many as possible) and a comma
  • [^(),$]+ - one or more chars other than (, ), $ and a comma
  • (?=(?:\$[^()]*)?\)) - the current location must be immediately followed with an optional occurrence of a $ char and then zero or more chars other than ( and ), and then a ) char.

An alternative:

var results = Regex.Matches(text, @"(?:\G(?!^)|\(DATA\$0)[^()]*?,([^(),$]+)(?=(?:\$[^()]*)?\))")
    .Cast<Match>()
    .Select(x => x.Groups[1].Value)
    .ToList();

See the regex demo. Details:

  • (?:\G(?!^)|\(DATA\$0) - either the end of the previous successful match, or (DATA$0 string
  • [^()]*? - zero or more chars other than (, ), ,, as few as possible
  • , - a comma
  • ([^(),$]+) - Group 1: one or more chars other than (, ), ,, $
  • (?=(?:\$[^()]*)?\)) - a positive lookahead matching the location that is immediately followed with an optional occurrence of a $ char followed with zero or more chars other than ( and ), and then a ) char.
Sign up to request clarification or add additional context in comments.

2 Comments

Okay, that works for the 1 sample data I sent above but I found out the data that we're receiving can actually have different numbers of values between $ per line: (DATA$0$24.0001,5.3038,26.0001,5.3055,28,5.3078$24.0002,5.2921,26,5.2965,28.0001,5.2914$24.0003,5.3183,26.0002,5.327,28.0002,5.3176$24.0004,2.2584,26.0002,2.2686,28.0003,2.2594$24.0001,44.7754,26.0001,45.7031,28,45.9595$24.0002,43.6157,26,44.3848,28.0001,43.9697$24.0003,42.4561,26.0002,37.7686,28.0002,38.0493$24.0004,9.082,26.0002,7.9468,28.0003,8.0566)
@BBousman Please check the two solutions now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.