AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

RegEx Frage

Ein Thema von hansklok · begonnen am 18. Jan 2016 · letzter Beitrag vom 18. Mai 2016
Antwort Antwort
hansklok

Registriert seit: 14. Apr 2004
Ort: Karlsruhe
318 Beiträge
 
Delphi 2010 Architect
 
#1

AW: RegEx Frage

  Alt 5. Feb 2016, 01:22
Wow, danke! Wenn es nicht kompliziert wäre, hätte ich die Frage eh nicht ins Forum geworfen

Im Prinzip erfüllt das Pattern ja seine Sache

Also nochmal zum Aufbau:
Code:
Level (Reference) Tag (Value)
Level = Zahl 0-99
Reference = von @-Zeichen umschlossener Wert
Tag = einzelnes Wort, wobei die Wörter FAMC FAMS und CHIL eine Auswirkung auf Value, die dann ebenfalls von @-Zeichen umgeben ist haben
Value = Rest der Zeile, abhängig vom Tag

Die eingeklammerten Werte sind optional, ABER ich hätte gern immer genau 4 Match-SubStrings, also auch NIL Matches sind erlaubt. Das macht es einfacher für mich die Daten weiterzuverarbeiten.

Das Pattern
Code:
(?x)
(0|[1-9][\d]*)\h+
(?:@?((?<=@)[^@]+(?=@)|(?!@))(?:@\h+)?)
(?<Special>FAM[SC]|CHIL)?
(?(Special)|(?<NoSpecial>\w+))
(?(Special)\h+@([^\v]*|)@|\h*([^\v]*|))
hat aber bis zu 6 Match-SubStrings

Also sollte folgendes rauskommen:
Code:
1 = Level
2 = (Reference)
3 = Tag (Special/NoSpecial)
4 = Value
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: RegEx Frage

  Alt 5. Feb 2016, 01:58
Wenn du einen Parser für eine Zeile schreiben würdest, hättest du zuverlässigere Ergebnisse und wärst wohl schon fertig.

Hier mal so ein Parser mit der stateless Bibliothek
Delphi-Quellcode:
unit Unit2;

interface

uses
  System.SysUtils,
  stateless;

type
  TRow = record
  public
    Level : Integer;
    Reference: string;
    Tag : string;
    Value : string;
    RefValue : string;
  public
    class function Parse( const AStr: string ): TRow; static;
    function ToString( ): string;
  end;

implementation

uses
  System.StrUtils;

class function TRow.Parse( const AStr: string ): TRow;
type
{$SCOPEDENUMS ON}
  TParserState = ( Level, ReferenceOrTag, Reference, TagStart, Tag, ValueOrRefValue, Value, RefValue, Finished, Error );
  TParseerTrigger = ( ParseChar, ParseFinish );
{$SCOPEDENUMS OFF}
  TRowParserSM = TStateMachine<TParserState, TParseerTrigger>;
var
  sm : TRowParserSM;
  pc : TRowParserSM.TTriggerWithParameters<Char>;
  buffer : string;
  c : Char;
  res : TRow;
  errorTransition: TRowParserSM.TTransition;
begin
  buffer := '';
  sm := TRowParserSM.Create( TParserState.Level );
  try
    pc := sm.SetTriggerParameters<Char>( TParseerTrigger.ParseChar );

{$REGION 'Configuration'}
    { Level }

    sm.Configure( TParserState.Level )
    {} .OnEntryFrom<Char>( pc,
      procedure( const c: Char; const t: TRowParserSM.TTransition )
      begin
        if t.IsReentry
        then
          buffer := buffer + c;
      end )
    {} .OnExit(
      procedure( const t: TRowParserSM.TTransition )
      begin
        if not t.IsReentry
        then
          begin
            res.Level := StrToInt( buffer );
            buffer := '';
          end;
      end )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Error )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          '0' .. '9':
            Result := TParserState.Level;
          ' ':
            begin
              if buffer.IsEmpty
              then
                Result := TParserState.Error
              else
                begin
                  Result := TParserState.ReferenceOrTag;
                end;
            end;
        else
          Result := TParserState.Error;
        end;
      end );

    { ReferenceOrTag }

    sm.Configure( TParserState.ReferenceOrTag )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Error )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          '@':
            Result := TParserState.Reference;
          ' ':
            Result := TParserState.ReferenceOrTag;
          'A' .. 'Z':
            Result := TParserState.Tag;
        else
          Result := TParserState.Error;
        end;
      end );

    { Reference }

    sm.Configure( TParserState.Reference )
    {} .OnEntryFrom<Char>( pc,
      procedure( const c: Char; const t: TRowParserSM.TTransition )
      begin
        if t.IsReentry
        then
          buffer := buffer + c;
      end )
    {} .OnExit(
      procedure( const t: TRowParserSM.TTransition )
      begin
        if not t.IsReentry
        then
          begin
            res.Reference := buffer;
            buffer := '';
          end;
      end )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Error )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          '@':
            if buffer.IsEmpty
            then
              Result := TParserState.Error
            else
              Result := TParserState.TagStart;
        else
          Result := TParserState.Reference;
        end;
      end );

    { TagStart }

    sm.Configure( TParserState.TagStart )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Error )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          ' ':
            Result := TParserState.TagStart;
          'A' .. 'Z':
            Result := TParserState.Tag;
        else
          Result := TParserState.Error;
        end;
      end );

    { Tag }

    sm.Configure( TParserState.Tag )
    {} .OnEntryFrom<Char>( pc,
      procedure( const c: Char )
      begin
        buffer := buffer + c;
      end )
    {} .OnExit(
      procedure( const t: TRowParserSM.TTransition )
      begin
        if not t.IsReentry
        then
          begin
            res.Tag := buffer;
            buffer := '';
          end;
      end )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Finished )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          'A' .. 'Z':
            if buffer.Length >= 4
            then
              Result := TParserState.Error
            else
              Result := TParserState.Tag;
          ' ':
            Result := TParserState.ValueOrRefValue;
        else
          Result := TParserState.Error;
        end;
      end );

    { ValueOrRefValue }

    sm.Configure( TParserState.ValueOrRefValue )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Finished )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          '@':
            Result := TParserState.RefValue;
          ' ':
            Result := TParserState.ValueOrRefValue;
        else
          Result := TParserState.Value;
        end;
      end );

    { Value }

    sm.Configure( TParserState.Value )
    {} .OnEntryFrom<Char>( pc,
      procedure( const c: Char; const t: TRowParserSM.TTransition )
      begin
        buffer := buffer + c;
      end )
    {} .OnExit(
      procedure( const t: TRowParserSM.TTransition )
      begin
        if not t.IsReentry
        then
          begin
            res.Value := buffer;
            buffer := '';
          end;
      end )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Finished )
    {} .PermitReentry( TParseerTrigger.ParseChar );

    { RefValue }

    sm.Configure( TParserState.RefValue )
    {} .OnEntryFrom<Char>( pc,
      procedure( const c: Char; const t: TRowParserSM.TTransition )
      begin
        if t.IsReentry
        then
          buffer := buffer + c;
      end )
    {} .OnExit(
      procedure( const t: TRowParserSM.TTransition )
      begin
        if not t.IsReentry
        then
          begin
            res.RefValue := buffer;
            buffer := '';
          end;
      end )
    {} .Permit( TParseerTrigger.ParseFinish, TParserState.Error )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          '@':
            if buffer.IsEmpty
            then
              Result := TParserState.Error
            else
              Result := TParserState.Finished;
        else
          Result := TParserState.RefValue;
        end;
      end );

    { Finished }

    sm.Configure( TParserState.Finished )
    {} .PermitReentry( TParseerTrigger.ParseFinish )
    {} .PermitDynamic<Char>( pc,
      function( const c: Char ): TParserState
      begin
        case c of
          ' ':
            Result := TParserState.Finished;
        else
          Result := TParserState.Error;
        end;
      end );

    { Error }

    sm.Configure( TParserState.Error )
    {} .OnEntry(
      procedure( const t: TRowParserSM.TTransition )
      begin
        errorTransition := t;
      end );
{$ENDREGION}
    { Parse the string }

    for c in AStr do
      begin
        if not sm.CanFire( TParseerTrigger.ParseChar )
        then
          break;
        sm.Fire<Char>( pc, c );
      end;

    { Fire Finish Trigger }

    if sm.CanFire( TParseerTrigger.ParseFinish )
    then
      sm.Fire( TParseerTrigger.ParseFinish );

    { Check the final state }

    if sm.State <> TParserState.Finished
    then
      raise Exception.Create( errorTransition.ToString );

    Result := res;

  finally
    sm.Free;
  end;
end;

function TRow.ToString: string;
begin
  Result := Level.ToString( )
  {} + IfThen( Reference.IsEmpty, '', ' @' + Reference + '@' )
  {} + ' ' + Tag.ToUpperInvariant( )
  {} + IfThen( Value.IsEmpty, '', ' ' + Value )
  {} + IfThen( RefValue.IsEmpty, '', ' @' + RefValue + '@' );
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 5. Feb 2016 um 10:57 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:42 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz