Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract GUID from line in C#

Tags:

c#

I try to simplify some legacy code using IndexOf to retrieve a GUID from lines. Can I further simplify the code below to get rid of using guids.Any and guids.First?

// Code using regular expression
private static string RetrieveGUID2(string[] lines)
{
    string guid = null;
    foreach (var line in lines)
    {
        var guids = Regex.Matches(line, @"[{(]?[0-9A-F]{8}[-]?([0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?")
            .Cast<Match>().Select(m => m.Value);
        if (guids.Any())
        {
            guid = guids.First();
            break;
        }
    }
    return guid;
}

Below the legacy code given in a sample that compiles:

using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var lines = new[]
            {
                "</ItemGroup>\n",
                "<PropertyGroup\n",
                "Label = \"Globals\">\n",
                "<ProjectGuid>{A68615F1-E672-4B3F-B5E3-607D9C18D1AB}</ProjectGuid>\n",
                "</PropertyGroup>\n"
            };

            Console.WriteLine(RetrieveGUID(lines));
            Console.WriteLine(RetrieveGUID2(lines));
        }

        // Legacy code
        private static string RetrieveGUID(string[] lines)
        {
            string guid = null;
            foreach (var line in lines)
            {
                var startIdx = line.IndexOf("<ProjectGuid>{", StringComparison.Ordinal);
                if (startIdx < 0) continue;
                var endIdx = line.IndexOf("</ProjectGuid>", StringComparison.Ordinal);
                if (endIdx < 0) continue;
                startIdx += "<ProjectGuid>".Length;
                var guidLen = endIdx - startIdx;
                guid = line.Substring(startIdx, guidLen);
                break;
            }
            return guid;
        }

        // Code using regular expression
        private static string RetrieveGUID2(string[] lines)
        {
            string guid = null;
            foreach (var line in lines)
            {
                var guids = Regex.Matches(line, @"[{(]?[0-9A-F]{8}[-]?([0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?")
                    .Cast<Match>().Select(m => m.Value);
                if (guids.Any())
                {
                    guid = guids.First();
                    break;
                }
            }
            return guid;
        }
    }
}
like image 814
Less White Avatar asked May 30 '17 14:05

Less White


3 Answers

Yes, you can. Cause you return only the first match of regex, you can use Regex.Match instead of Regex.Matches.

private static string RetrieveGUID2(string[] lines)
{
    foreach (var line in lines)
    {
        var match = Regex.Match(line, @"[{(]?[0-9A-F]{8}[-]?([0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?");
        if (match.Success)
          return match.Value;
    }

    return null;
}
like image 105
Mark Shevchenko Avatar answered Oct 23 '22 11:10

Mark Shevchenko


use a foreach loop which breaks out on first iteration - this is actually how First and FirstOrDefault are implemented

foreach(var nextGuid in guids) { guid = nextGuid; break; }

Simplifying it further, you could use FirstOrDefault, which will not throw an error if there are no objects

return Regex
    .Matches(line, @"[{(]?[0-9A-F]{8}[-]?([0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?")
    .Cast<Match>()
    .Select(m => m.Value)
    .FirstOrDefault();
like image 36
David Avatar answered Oct 23 '22 09:10

David


Just to offer an alternative using Guid.TryParse():

public static Guid? RetrieveGuid(IEnumerable<string> lines)
{
    Guid? parseGuid(string text) => Guid.TryParse(text, out Guid guid) ? (Guid?) guid : null;
    return lines.Select(parseGuid).FirstOrDefault(guid => guid != null);
}

Or equivalently:

public static Guid? RetrieveGuid(IEnumerable<string> lines)
{
    return lines.Select(line => Guid.TryParse(line, out Guid guid) ? (Guid?)guid : null)
        .FirstOrDefault(guid => guid != null);
}

This returns a Guid? rather than a string, and a result of null means that no valid Guid was parsed.

like image 39
Matthew Watson Avatar answered Oct 23 '22 11:10

Matthew Watson