使用正则表达式在txt文件中查找GUID字符串,其中" id ="附在它上面

时间:2015-03-24 23:57:17

标签: c# regex

下面的代码运行良好,目标是在XML文件中查找GUID字符串。因此它会找到字符串A03DD607-90BF-4077-ADA8-C6E76F9D4759,但现在我正在尝试将正则表达式更改为仅查找:

id="A03DD607-90BF-4077-ADA8-C6E76F9D4759"

而不是

A03DD607-90BF-4077-ADA8-C6E76F9D4759

这是我的代码:

    //obtain all GUIDs in the XML file
    using (StreamReader sr = File.OpenText(xmlFile))
    {
        string s = String.Empty;
        while ((s = sr.ReadLine()) != null)
        {
            MatchCollection guids = Regex.Matches(s, @"(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}");
            for (int i = 0; i < guids.Count; i++)
            {
                Console.WriteLine(guids[i].Value);
                guidList.Add(guids[i].Value.ToUpper());
            }
        }
    }

2 个答案:

答案 0 :(得分:1)

我会将文字Guid的识别推迟到Guid.TryParse()。这会使你的正则表达式减少到这样:

private const RegexOptions rxOptions = RegexOptions.IgnoreCase
                                     | RegexOptions.ExplicitCapture
                                     | RegexOptions.CultureInvariant
                                     ;

private static readonly Regex rxGuidId = new Regex( @"id=""(?<guid>[^""]+)""", rxOptions );

然后你可以在LINQ中完成所有操作,就像这样:

private static Guid[] ExtractGuidsFromText( string s )
{
  return rxGuidId
         .Matches( s ?? "" )
         .Cast<Match>()
         .Where( m => m.Success )
         .Select( m => {
           Guid instance;
           bool validGuid = Guid.TryParse( m.Groups["guid"].Value , out instance ) ;
           return validGuid ? (Guid?)instance : (Guid?)null ;
         })
         .Where( g => g.HasValue )
         .Select( g => g.Value )
         .ToArray()
         ;
}

LINQ解决方案比直接,简单的方式更简洁,更优雅,更慢并且使用更多内存:

private static IEnumerable<Guid> ExtractGuidsFromText( string s )
{
  for ( Match m = rxGuidId.Match( s ?? "" ) ; m.Success ; m = m.NextMatch() )
  {
    Guid instance;
    bool parsed = Guid.TryParse( m.Groups["guid"].Value , out instance ) ;
    if ( parsed ) yield return instance;
  }
}

但是既然你有一个XML文件,你当然可以使用内置的.Net支持XML,并通过Xpath(//@id)选择你的节点集应该这样做,只是丢弃那些没有有效GUID的节点。

或者您可以使用XML阅读器并懒洋洋地找到它们:

static IEnumerable<string> ReadGuidsFromXml( TextReader input )
{
  using ( XmlReader reader = XmlReader.Create( input ) )
  {
    while ( reader.Read() )
    {
      if ( reader.NodeType != XmlNodeType.Element ) continue ;

      for ( bool hasAttributes = reader.MoveToFirstAttribute() ; hasAttributes ; hasAttributes = reader.MoveToNextAttribute() )
      {
        if ( !string.Equals( reader.Name , "id" , StringComparison.OrdinalIgnoreCase ) ) continue ;

        Guid guid;
        if ( Guid.TryParse( reader.Value , out guid ) )
        {
          yield return guid;
        }

      }

    }

  }
}

答案 1 :(得分:0)

您可以使用以下代码替换相应的代码行:

   MatchCollection guids = Regex.Matches(s, @"id=""(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}""");

在C#字符串文字中,文字引号必须加倍。