none
Regex: Anzahl Zeichen aus Pattern ermitteln RRS feed

  • Frage

  • Hallo allerseits!
     
    In meiner Applikation habe ich diverse reguläre Ausdrücke wie "[0-9][0-9A-F]",
    "[0-9]{6}" oder ".{30}". Allen Pattern ist es gemein, daß sie auf eine konstante
    Anzahl von Zeichen matchen. Gibt es eine Möglichkeit diese Anzahl aus dem
    Pattern heraus zu ermitteln?
     
    TIA
     
    Grüße
    Thomas
     
    --
    Any problem in computer science can be solved with another layer
    of indirection. But that usually will create another problem.
                                       David Wheeler
     
    Freitag, 2. März 2012 08:38

Antworten

  • Also direkt ermitteln geht nicht, aber du kannst deinen ganzen ausdruck einklammern und dann folgendes anhängen: "|^{5}$". Also dann bspw. so hier:

    "(?<VSTRA>[0-9][0-9A-F])|^{5}$"

    Dabei wird überprüft ob zwischen Anfang (^) und Ende ($) 5 Zeichen liegen. Wenn ja, und dein Anderer Ausdruck vor "|" stimmt, dann gibt Regex.IsMatch(input, pattern); true zurück.

    Hier sind noch die MSDN-Artikel zu Regex, Regex.IsMatch und den regulären Ausdrücken.


    Koopakiller - http://koopakiller.ko.ohost.de/

    Montag, 5. März 2012 16:06
    Moderator

Alle Antworten

  • Wieso brauchst du das? Ich würde einfach

    if(MeinString.Length == 12)
    //bzw.
    if(MeinString.Length == 12 && Regex.IsMatch(MeinString, Pattern);

    benutzen, die Pattern könnten dann ja eh nur die Zahl auf die richtigkeit überprüfen und ich glaub so gehts schneller ;)

    Koopakiller - http://koopakiller.ko.ohost.de/

    Freitag, 2. März 2012 14:21
    Moderator
  • Hallo Koopakiller!
     
    > Wieso brauchst du das?
     
    Ich hab's mir schon gedacht, daß diese Frage kommen wird ;-)
     
    Mein Programm soll Dateien auf formelle Korrektheit prüfen. Die einzelnen Zeilen dieser Datei haben dabei eine fixe
    Länge und entsprechen jeweils einem Datensatz. Es gibt ca. 15 verschiedene Datensatzarten, die wiederum aus bis zu
    25 Feldern mit fixer Länge bestehen.
     
    Für die Felddefinitionen hab' ich eine eigene Klasse mit Startposition, Länge und Regex-Pattern:
     
       class Field
       {
          public int Start { get; set; }
          public int Length { get; set; }
          public string Pattern { get; set; }
       }  
     
    Für jede Satzart habe ich dann eine List von Felddefinitionen:
     
       List<Field> fields = new List<Field>();
     
       fields.Add(new Field() { Start = 1, Length = 2, Pattern = "(?<VSTRA>[0-9][0-9A-F])" });
       fields.Add(new Field() { Start = 3, Length = 1, Pattern = "(?<BLNDA>[1-9])" });
       fields.Add(new Field() { Start = 4, Length = 6, Pattern = "(?<VPNR>[0-9]{6})" });
       fields.Add(new Field() { Start = 10, Length = 2, Pattern = "(?<VPADR>[0-9]{2})" });
       ...
     
    Aus diesen Felddefinitionen baue ich erst ein "Gesamt-Pattern" für die ganze Zeile und prüfe, ob diese entspricht.
    Falls nicht, extrahiere ich anhand von Start und Length Teilstrings aus der Zeile und prüfe sie gegen das jeweilige
    Pattern.
     
    Langer Rede kurzer Sinn: ich möchte mir - wenns einfach geht - die explizite Angabe von Length sparen.
     
     
    Grüße
    Thomas
     
    --
    Any problem in computer science can be solved with another layer
    of indirection. But that usually will create another problem.
                                       David Wheeler
     
    Montag, 5. März 2012 09:21
  • Also direkt ermitteln geht nicht, aber du kannst deinen ganzen ausdruck einklammern und dann folgendes anhängen: "|^{5}$". Also dann bspw. so hier:

    "(?<VSTRA>[0-9][0-9A-F])|^{5}$"

    Dabei wird überprüft ob zwischen Anfang (^) und Ende ($) 5 Zeichen liegen. Wenn ja, und dein Anderer Ausdruck vor "|" stimmt, dann gibt Regex.IsMatch(input, pattern); true zurück.

    Hier sind noch die MSDN-Artikel zu Regex, Regex.IsMatch und den regulären Ausdrücken.


    Koopakiller - http://koopakiller.ko.ohost.de/

    Montag, 5. März 2012 16:06
    Moderator
  • Hallo Koopakiller!
     
    > Also direkt ermitteln geht nicht
     
    Schade. Trotzdem vielen Dank für Deine Mühe.
     
    > aber du kannst deinen ganzen ausdruck einklammern und dann folgendes anhängen: "|^{5}$".
     
    Das funktioniert nicht, weil ich ja bei der Prüfung aus mehreren Patterns ein gesamtes zusammenbaue und ^ bzw. $ ja
    nicht mitten in einem Pattern stehen dürfen. Der Vollständigkeit halber hier ein komplett lauffähiges Beispiel dessen,
    was ich mache:
     
       class Field
       {
          public int Start { get; set; }
          public int Length { get; set; }
          public string Pattern { get; set; }
       }
     
       class Parser
       {
          private List<Field> fields;
          private string fullPattern;
     
          public Parser(List<Field> fields)
          {
             StringBuilder builder = new StringBuilder("^");
     
             foreach (Field field in fields)
             {
                builder.Append(field.Pattern);
             }
     
             builder.Append("$");
             this.fullPattern = builder.ToString();
             this.fields = fields;
          }
     
          public void Parse(string line)
          {
             Match match = Regex.Match(line, fullPattern);
     
             if (match.Success)
             {
                Console.WriteLine("Satz OK");
             }
             else
             {
                foreach (Field field in this.fields)
                {
                   string part = line.Substring(field.Start - 1, field.Length);
                   match = Regex.Match(part, field.Pattern);
     
                   if (!match.Success)
                   {
                      Console.WriteLine("'{0}' entspricht nicht {1}", part, field.Pattern);
                   }
                }
             }
          }
       }
     
       class Program
       {
          static void Main(string[] args)
          {
             List<Field> fields = new List<Field>();
            
             fields.Add(new Field() { Start = 1, Length = 2, Pattern = "(?<VSTRA>[0-9][0-9A-F])" });
             fields.Add(new Field() { Start = 3, Length = 1, Pattern = "(?<BLNDA>[1-9])" });
             fields.Add(new Field() { Start = 4, Length = 6, Pattern = "(?<VPNR>[0-9]{6})" });
             fields.Add(new Field() { Start = 10, Length = 2, Pattern = "(?<VPADR>[0-9]{2})" });
     
             Parser parser = new Parser(fields);
             string good = "1B796674999";
             string bad = "1B796cxb999";
     
             parser.Parse(good);   // --> Satz OK
             parser.Parse(bad);    // --> '96cxb9' entspricht nicht (?<VPNR>[0-9]{6})
          }
       }
     
     
    Grüße
    Thomas
     
    --
    Any problem in computer science can be solved with another layer
    of indirection. But that usually will create another problem.
                                       David Wheeler
     
     
     
    Mittwoch, 7. März 2012 08:33