.NET Regex:如何提取IPv6地址部分

时间:2010-05-28 20:01:25

标签: c# .net asp.net vb.net regex

问题:.NET正则表达式字符串如何提取IPv6地址?

我可以让它提取一个简单的IPv6地址,如“1050:0:0:0:5:600:300c:326b” 但不是冒号格式(“ff06 :: c3”);

我的问题是,它应该为::之间的每个省略值提取0: 我该怎么做?

在我的代码+说明下面。

通过省略前导零来指定IPv6地址。
例如,IPv6地址1050:0000:0000:0000:0005:0600:300c:326b
可写为1050:0:0:0:5:600:300c:326b。
双冒号
使用双冒号(::)代替一系列零来指定IPv6地址。
例如,IPv6地址ff06:0:0:0:0:0:0:c3
可以写成ff06 :: c3。
双冒号只能在IP地址中使用一次。

        strInputString = "ff06::c3";
        strInputString = "1050:0000:0000:0000:0005:0600:300c:326b";

        string strPattern = "([A-Fa-f0-9]{1,4}:){7}([A-Fa-f0-9]{1,4})";
        //strPattern = @"\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\z";

        //strPattern = @"(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\Z)|(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\Z)|(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\Z)|(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\Z)|(\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\Z)|(\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\Z)|(\A(([0-9a-f]{1,4}:){1,7}|:):\Z)|(\A:(:[0-9a-f]{1,4}){1,7}\Z)|(\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|(\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|(\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|(\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|(\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z) ";
        //strPattern = @"/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/";
        //strPattern = @"(:?[0-9a-fA-F]{1,4}:){7}([0-9a-fA-F]{1,4})\z";
        //strPattern = @"\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\z";


        //strPattern = @"\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}:)*)(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z";
        //strPattern = @"/^(?:(?:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9](?::|$)){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))$/i";

        System.Text.RegularExpressions.Regex reValidationRule = new System.Text.RegularExpressions.Regex("^" + strPattern + "$");


        if (reValidationRule.Match(strInputString).Success) // If matching pattern
        {
            System.Text.RegularExpressions.Match maResult = System.Text.RegularExpressions.Regex.Match(strInputString, strPattern);
            // Console.WriteLine(maResult.Groups.Count)

            string[] astrReturnValues = new string[4];


            System.Text.RegularExpressions.GroupCollection gc = maResult.Groups;
            System.Text.RegularExpressions.CaptureCollection cc;

            int counter;
            //System.Web.Script.Serialization.JavaScriptSerializer jssJSONserializer  = new System.Web.Script.Serialization.JavaScriptSerializer();
            //Console.WriteLine(jssJSONserializer.Serialize());
            // Loop through each group.
            for (int i = 0; i < gc.Count; i++)
            {
                Console.WriteLine("Group: {0}", i);
                cc = gc[i].Captures;
                counter = cc.Count;

                // Print number of captures in this group.
                Console.WriteLine("Captures count = " + counter.ToString());

                // Loop through each capture in group.
                for (int ii = 0; ii < counter; ii++)
                {
                    Console.WriteLine("Capture: {0}", ii);
                    // Print capture and position.
                    Console.WriteLine(cc[ii] + "   Starts at character " +
                        cc[ii].Index);
                }
            }

2 个答案:

答案 0 :(得分:2)

    private static IEnumerable<string> Parse(string input)
    {
        const string partPattern = @"([A-Fa-f0-9]{1,4})";
        string longPattern = string.Format(@"{0} (?:\:{0})*", partPattern); //Group 1 -> 2
        string compactPattern = string.Format(@"{0} (?:\:{0})* \:\: {0} (?:\:{0})*", partPattern, RegexOptions.IgnorePatternWhitespace); //Groups 3 ->6
        string completePattern = string.Format(@"^{0}$ | ^{1}$", longPattern, compactPattern);
        var match = Regex.Match(input, completePattern, RegexOptions.IgnorePatternWhitespace);
        if (match.Success)
        {
            if (match.Groups[1].Success)
            {
                yield return match.Groups[1].Value.PadLeft(4, '0');
                for (int i = 0; i < match.Groups[2].Captures.Count; ++i)
                    yield return match.Groups[2].Captures[i].Value.PadLeft(4, '0');
            }
            else
            {
                var count = 6 - match.Groups[4].Captures.Count - match.Groups[6].Captures.Count;

                //First part
                yield return match.Groups[3].Value.PadLeft(4, '0');
                for (int i = 0; i < match.Groups[4].Captures.Count; ++i)
                    yield return match.Groups[4].Captures[i].Value.PadLeft(4, '0');

                //:: block
                for (int i = 0; i < count; ++i)
                    yield return "0000";

                //Second part
                yield return match.Groups[5].Value.PadLeft(4, '0');
                for (int i = 0; i < match.Groups[6].Captures.Count; ++i)
                    yield return match.Groups[6].Captures[i].Value.PadLeft(4, '0');
            }
        }
        else
            throw new Exception("No match");
    }

这样的事情应该有效。基本思路是将包含::和其余地址的大小写分成两种不同的模式。我使用了这样的假设:::永远不会在开头或结尾,所以如果不能保持你将不得不修改模式。

答案 1 :(得分:0)

Regex.Replace()可能有助于您的事业。您可以像这样使用它来返回一个变换的字符串,其中“::”替换为字符串中的“:0:”

var myStr = "test::me";
Console.WriteLine( Regex.Replace(myStr, @"::", ":0:") );

我用LINQPad对它进行了测试,它对我来说效果很好。