Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>it tink the best solution would be a Tokenizer/Parser to get the Information you want. <br/> I don't think you can handle it (efficient and transparent for others) with a single Regex. In my opinion a Regex is not always the Solution for complex string problems.<br/><br/> I also think, that a large Regex is not maintainable at any time and should therefore be avoided. (Try it by yourself, get any complex Regex from any Page from the Internet. Don't read, what the expression should do, and try describing the functionality of the expression. You would be supprised what the writer expected, and what you expect the expression to do.<br/><br/> <strong>Simple Regex to bold my point:</strong><br/></p> <p>What does this Regex do?</p> <pre><code>(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]) </code></pre> <p>This Regex is the implementation of the <code>RFC 2822</code> from <a href="http://www.regular-expressions.info/email.html" rel="nofollow">this</a> page.</p> <p>And this one is a reduced one from the same page.</p> <pre><code>[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])? </code></pre> <p>Both can be used to <strong>check a e-mail address</strong>! Did you expect this?</p> <h2>Solution:</h2> <p>Create a Tokenzier/Parser: So to show you how i would solve this problem I prepared a working sample for you. <br/> Just Copy paste it to a Console Application, should work fine :-)<br/> Please give me feedback about my code and if my helps was usefull for you.</p> <h2>Sample explanation:</h2> <p>Create a Tokenizer, which splits the expressions into matching tokens. In this case the Tokens derive from Interface <code>IToken</code>.<br/> The Tokens are created by Line and than by a regex Match with groups. See method <code>Tokenize</code> and <code>TokenizeLine</code>. They do the hard work.</p> <ol> <li>Splitting (Line and Spaces)</li> <li>Matching (if Vsan or Interface)</li> </ol> <p><br/> After Splitting it up it gets real simple. Just move forward through the Tokens and create the <code>VSan</code> and <code>Interface</code> Objects.<br/> The Tokens are order after the order of the String Groups (defined by Regex in Tokenize) so moving through the list is always: <br/></p> <pre><code>VSan Interface Interface Interface Vsan Interface Interface </code></pre> <p>So you can easy create a VSan Object and adding all Interfaces afterwards. If the next VSan Token is in line just create a new VsanObject an continue with adding Interfaces to the new Instance. <br/></p> <p>Now you have a list of Vsans which contains a List of Interfaces which you can use .<br/> I overwrote the <code>ToString</code> Method to make the result visible.</p> <h2>Sample Code:</h2> <pre><code>public static class Program{ static string VsanString = @"vsan 1 interfaces: fc2/1 vsan 10 interfaces: fc1/1 fc1/2 fc1/3 fc1/4 fc1/5 fc1/6 fc1/7 fc1/8 fc1/9 fc1/10 fc1/11 fc1/12 fc1/13 fc1/14 fc1/15 fc1/16 "; public static void Main (string[] args) { VSanTokenizer vSanTokenizer = new VSanTokenizer(VsanString); IList&lt;IToken&gt; tokens = vSanTokenizer.Tokens; VsanTokenInterpreter vsanTokenInterpreter = new VsanTokenInterpreter(tokens); IList&lt;IVSan&gt; vSans = vsanTokenInterpreter.VSans; foreach (IVSan vSan in vSans) { Console.WriteLine(vSan.ToString()); } Console.WriteLine("Please press return to quit."); Console.ReadLine(); } } interface IVSan { int Number { get; } IList&lt;IInterface&gt; Interfaces { get; } } class VSan : IVSan { private readonly IList&lt;IInterface&gt; interfaces; private readonly int number; public VSan(int number, IList&lt;IInterface&gt; interfaces) { this.number = number; this.interfaces = interfaces; } public override string ToString() { StringBuilder toString = new StringBuilder(); toString.Append("Vsan with Number: "); toString.Append(number); toString.Append(" has following Interfaces:"); toString.AppendLine(""); foreach (IInterface @interface in Interfaces) { toString.Append("Intefaces with Name: "); toString.Append(@interface.Name); toString.AppendLine(""); } return toString.ToString(); } #region Implementation of IVSan public int Number { get { return number; } } public IList&lt;IInterface&gt; Interfaces { get { return interfaces; } } #endregion } interface IInterface { string Name { get; } } class Interface : IInterface { private readonly string name; public Interface(string name) { this.name = name; } #region Implementation of IInterface public string Name { get { return name; } } #endregion } interface IToken { string Value { get; } } interface IVsanToken : IToken { int VsanInterfaceNumber { get; } } internal abstract class AbstractToken : IToken { private readonly string value; public AbstractToken(string value) { this.value = value; } #region Implementation of IToken public string Value { get { return value; } } #endregion } class VsanToken : AbstractToken, IVsanToken { private readonly int vsanInterfaceNumber; public VsanToken(string value) : base(value) { vsanInterfaceNumber = int.Parse(value); } #region Implementation of IVsanToken public int VsanInterfaceNumber { get { return vsanInterfaceNumber; } } #endregion } class InterfaceToken : AbstractToken, IInterfaceToken { private readonly int firstNumber; private readonly int secondNumber; public InterfaceToken(string value) : base(value) { Match match = Regex.Match(value, "fc([0-9])/([0-9]+)"); Group firstNumberGroup = match.Groups[1]; Group secondNumberGroup = match.Groups[2]; firstNumber = int.Parse(firstNumberGroup.Value); secondNumber = int.Parse(secondNumberGroup.Value); } public int SecondNumber { get { return secondNumber; } } public int FirstNumber { get { return firstNumber; } } } interface IInterfaceToken : IToken { //Edited: Added Second and FirstNumber to Interface so it can be accessed int SecondNumber { get; } int FirstNumber { get ; } } class VSanTokenizer { private readonly string vSanString; private IList&lt;IToken&gt; tokens; public VSanTokenizer(string vSanString) { this.vSanString = vSanString; tokens = Tokenize(vSanString); } public string VSanString { get { return vSanString; } } private IList&lt;IToken&gt; Tokenize(string vSanString) { List&lt;IToken&gt; tokens = new List&lt;IToken&gt;(); StringReader reader = new StringReader(vSanString); string readLine = reader.ReadLine(); while (readLine != null) { IList&lt;IToken&gt; tokenizeLine = TokenizeLine(readLine); tokens.AddRange(tokenizeLine); readLine = reader.ReadLine(); } return tokens; } private IList&lt;IToken&gt; TokenizeLine(string readLine) { IList&lt;IToken&gt; tokens = new List&lt;IToken&gt;(); Match vsanInterfaceDeclartion = Regex.Match(readLine, "vsan ([0-9]+) interfaces:"); if (vsanInterfaceDeclartion.Success) { Group numberGroup = vsanInterfaceDeclartion.Groups[1]; VsanToken vsanToken = new VsanToken(numberGroup.Value); tokens.Add(vsanToken); return tokens; } Match vsanInterface = Regex.Match(readLine, "(fc[0-9]/[0-9]+)"); if (vsanInterface.Success) { GroupCollection groupCollection = vsanInterface.Groups; foreach (Group vsanInterfaceGroup in groupCollection) { string value = vsanInterfaceGroup.Value; IToken token = new InterfaceToken(value); tokens.Add(token); } } return tokens; } public IList&lt;IToken&gt; Tokens { get { return tokens; } } } class VsanTokenInterpreter { private readonly IList&lt;IToken&gt; tokens; private readonly IList&lt;IVSan&gt; vSans; public VsanTokenInterpreter(IList&lt;IToken&gt; tokens) { this.tokens = tokens; this.vSans = ParseTokens(tokens); } private IList&lt;IVSan&gt; ParseTokens(IList&lt;IToken&gt; tokens) { IList&lt;IVSan&gt; vsans = new List&lt;IVSan&gt;(); IVSan currentVSan = null; foreach (IToken token in tokens) { if (token is IVsanToken) { currentVSan = CreateVSan((IVsanToken)token); vsans.Add(currentVSan); } else if (token is IInterfaceToken) { if (currentVSan == null) throw new Exception("First Vsan Line has to be declared!"); IInterface inter = CreateInterface((IInterfaceToken)token); currentVSan.Interfaces.Add(inter); } } return vsans; } protected virtual IInterface CreateInterface(IInterfaceToken interfaceToken) { //Edited: you can now access the First/Second Number from the Interface Token and use it to create the Instance of your interface: int firstNumber = interfaceToken.FirstNumber; int secondNumber = interfaceToken.SecondNumber; return new Interface(interfaceToken.Value); } protected virtual IVSan CreateVSan(IVsanToken vsanToken) { return new VSan(vsanToken.VsanInterfaceNumber, new List&lt;IInterface&gt;()); } public IList&lt;IVSan&gt; VSans { get { return vSans; } } public IList&lt;IToken&gt; Tokens { get { return tokens; } } } </code></pre> <h2>Result and Conclusion:</h2> <p>As a result you get a IVsan which contains the IInterfaces. You can use this Model in your code to get Information you looking for. <br/></p> <ol> <li>By using a Object Model you can change the parsing at any time, without changing anything in your business logic.</li> <li>The Parsing logic is more simple and understandable than in Regex</li> <li>There are readable Exception possible (for user Input)</li> <li>You can resolve int/bools a.s.o. during transformation</li> <li>Your colleagues can handle and maintain your code.</li> </ol> <p>Please ask me if you have furhter questions, i would be glad helping you! Please also give me feedback, I'm open for new impressions!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload