Alex: Regulärer Ausdruck (Zahl darf nicht auf 81100) enden

Hallo,

ich habe eine Liste von Zahlen von 200000 bis 399999 (das die Liste keine anderen Zahlen/Strings beinhaltet ist sichergestellt).

Nun sollen alle diese Zahlen angezeigt werden mit Ausnahme derer, die auf 81100 enden. Diese sollen nun mithilfe von Perl, reguläre Ausdrücke herausgefiltert werden.

Mein Lösungsansatz [23](?!81100) scheint zu funktionieren. Der Ausdruck muss mindestens eine 2 oder 3 beinhalten, diesen darf aber keine 81100 folgen.

Aufgrund der Datenmenge kann ich nur schwierig prüfen, ob dadurch nicht ungewollt weitere Daten durch das Raster fallen und bitte deshalb um fachmännische Überprüfung des Codes.

Vielleicht gibt es ja auch noch eine elegantere Lösung.

Ich würde mich über sämtliche Verbesserungs-/Korrekturvorschläge sehr freuen.

Grüße
Alex

  1. @@Alex:

    nuqneH

    Vielleicht gibt es ja auch noch eine elegantere Lösung.

    Ja, keinen regulären Ausdruck einsetzen. Du willst 281100 und 381100 ausfiltern, also frage genau diese zwei Werte ab und verwende die geeignete Verknüpfung.

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. Hallo Gunnar,

      vielen Dank für deine Antwort.

      Ja, keinen regulären Ausdruck einsetzen.

      Leider habe ich in dem verwendeten Programm nur Perl reguläre Ausdrücke zur Filterung zur Verfügung.

      Du willst 281100 und 381100 ausfiltern, also frage genau diese zwei Werte ab

      Soweit klar, lediglich die 281100 und 381100 wüsste ich noch umzusetzen:
      [23][8][1][1][0][0], aber wenn ich alle Datensätze außer diese beiden haben will, da weiß ich mir derzeit nicht bzw. nur wie im ersten Thread beschrieben zu helfen.

      und verwende die geeignete Verknüpfung.

      Kannst du das näher erläutern? Gibt es eine Möglichkeit den regulären Ausdruck umzudrehen bspw. wie in PHP statt if($zahl==281100 || $zahl==381100) ... mit $zahl!= 281100 || $zahl!=381100) ...?

      1. Hallo,

        Leider habe ich in dem verwendeten Programm nur Perl reguläre Ausdrücke zur Filterung zur Verfügung.

        Eine wichtige Information! Du verwendest also kein Perl, sondern "irgendein Programm" mit reglären Ausdrücken nach Perl-Syntax...

        ich habe eine Liste von Zahlen von 200000 bis 399999 (das die Liste keine anderen Zahlen/Strings beinhaltet ist sichergestellt).

        wie sicher bist du dir da, Zitat:

        Aufgrund der Datenmenge kann ich nur schwierig prüfen[..]

        Kann auch zukünftig nichts anderes in der Liste auftauchen?

        Nun zu deinem Ausdruck:

        23

        Du prüfst auf eine 2 oder 3, die nicht von 81100 gefolgt werden. Es würde z.B. auch 2481100 durchgehen.

        Wenn du wirklich sicher gehen willst, sollte dein Ausdruck so lauten:
        [1](?!81100)\d{5}$
        d.h. eine 2 oder 3 am Anfang, der genau 5 Zahlen folgen, die nicht 81100 sein dürfen.

        vg ichbinich

        --
        Kleiner Tipp:
        Tofu schmeckt am besten, wenn man es kurz vor dem Servieren durch ein saftiges Steak ersetzt...

        1. 23 ↩︎

        1. Hallo Ichbinich,

          erstmal bitte ich um Entschuldigung, dass ich erst jetzt eine Rückmeldung auf deine und die anderen hilfreichen Mails gebe, aber heute war - wie meist - ein harter Arbeitstag.

          Leider habe ich in dem verwendeten Programm nur Perl reguläre Ausdrücke zur Filterung zur Verfügung.

          Eine wichtige Information! Du verwendest also kein Perl, sondern "irgendein Programm" mit reglären Ausdrücken nach Perl-Syntax...

          Ja genau, tut mir leid, dass ich das im Ursprungspost nicht mitgeteilt habe.

          ich habe eine Liste von Zahlen von 200000 bis 399999 (das die Liste keine anderen Zahlen/Strings beinhaltet ist sichergestellt).
          wie sicher bist du dir da, Zitat:
          Aufgrund der Datenmenge kann ich nur schwierig prüfen[..]
          Kann auch zukünftig nichts anderes in der Liste auftauchen?

          Nein, die Filterung bis dahin habe ich durch andere Filtermöglichkeiten des besagten Programms sichergestellt.

          Nun zu deinem Ausdruck:

          23

          Du prüfst auf eine 2 oder 3, die nicht von 81100 gefolgt werden. Es würde z.B. auch 2481100 durchgehen.

          Das ist soweit gewollt. Ausschließlich die Kombinationen 281100 bzw. 381100 sollen nicht vorkommen.

          Wenn du wirklich sicher gehen willst, sollte dein Ausdruck so lauten:
          [1](?!81100)\d{5}$
          d.h. eine 2 oder 3 am Anfang, der genau 5 Zahlen folgen, die nicht 81100 sein dürfen.

          Vielen Dank für diese Lösung und vielen Dank auch an alle Anderen, die sich beteiligt haben :-)

          Gruß
          Alex


          1. 23 ↩︎

      2. Om nah hoo pez nyeetz, Alex!

        Kannst du das näher erläutern? Gibt es eine Möglichkeit den regulären Ausdruck umzudrehen bspw. wie in PHP statt if($zahl==281100 || $zahl==381100) ... mit $zahl!= 281100 || $zahl!=381100) ...?

        Die Regeln von deMorgan sind hilfreich.

        Matthias

        --
        1/z ist kein Blatt Papier.

  2. gudn tach!

    ich habe eine Liste von Zahlen von 200000 bis 399999 (das die Liste keine anderen Zahlen/Strings beinhaltet ist sichergestellt).

    Nun sollen alle diese Zahlen angezeigt werden mit Ausnahme derer, die auf 81100 enden.

    hmm, bis hierhin wuerde ich sagen, dass man dafuer keinen so grossen aufwand betreiben muessten, sondern dass wohl das folgende das schnellste waere:
    print "$_\n" for (200000..(281100-1), (281100+1)..(381100-1), (381100+1)..399999);

    das waere auch schneller als

    for my $n (200000..399999){  
      print "$_\n" if $n!=281100 and $n!=381100;  
    }
    

    oder

    for my $n (200000..399999){  
      print "$n\n" if substr($n, -5) ne '81100';  
    }
    

    Diese sollen nun mithilfe von Perl, reguläre Ausdrücke herausgefiltert werden.

    das hat ichbinich zwar erklaert. aber es draengt sich trotzdem die frage auf: was genau moechtest du? ich denke, es waere besser, wenn du noch etwas mehr kontext erzaehlst, dann kann dir besser geholfen werden.

    prost
    seth

    1. Moin Moin!

      ich habe eine Liste von Zahlen von 200000 bis 399999 (das die Liste keine anderen Zahlen/Strings beinhaltet ist sichergestellt).

      Nun sollen alle diese Zahlen angezeigt werden mit Ausnahme derer, die auf 81100 enden.

      hmm, bis hierhin wuerde ich sagen, dass man dafuer keinen so grossen aufwand betreiben muessten, sondern dass wohl das folgende das schnellste waere:
      print "$_\n" for (200000..(281100-1), (281100+1)..(381100-1), (381100+1)..399999);

      Nirgendwo in der Fragestellung steht, dass die Liste LÜCKENLOS oder EINDEUTIG oder SORTIERT ist. Sie könnte es sein, dann wären deine Beispiele halbwegs ok. Vermutlich ist sie es aber nicht, damit erzeugen Deine Beispiele falsche oder wenigstens irreführende Ausgaben.

      es draengt sich trotzdem die frage auf: was genau moechtest du? ich denke, es waere besser, wenn du noch etwas mehr kontext erzaehlst, dann kann dir besser geholfen werden.

      Korrekt.

      Bis dahin kann man nur raten oder sehr allgemeine Antworten geben:

      * Das Tool zum Filtern von Listen und Arrays in Perl ist grep. (Wie immer geht es auch anders, aber das ist eine andere Geschichte.)

      * grep kann wahlweise einen Ausdruck oder einen Block für jedes Listen- bzw Array-Element auswerten. Für "alles außer" muß der Ausdruck bzw. der Block in aller Regel eine Negation enthalten.

      * Die letzten fünf Zeichen eines beliebigen Strings lassen sich z.B. über substr oder eine RegExp ermitteln, wobei substr geringfügig schneller ist. Relevant ist das nur für große Datenmengen.

      * Die letzten fünf Ziffern eines positiven Integer können (sofern Perl den Integer wirklich als Integer speichert und nicht wegen zu wenig Bits "heimlich" in Floats konvertiert) auch leicht über den Modulo-Operator bestimmt werden. Das sollte, sofern die Daten Perl-intern bereits Integer sind und nicht erst aus Strings umgerechnet werden müssen, noch schneller als substr sein.

      Um also aus einem Array @liste alle Elemente heraus zu fischen, deren letzten vier Stellen 1234 sind, nutzt man Code wie diesen:

        
      @ergebnis=grep /1234$/,@liste;  
      @ergebnis=grep { /1234$/ } @liste;  
      @ergebnis=grep { substr($_,-4) eq '1234' } @liste;  
      @ergebnis=grep { $_%10000==1234 } @liste;  
      
      

      Und um genau diese Elemente nicht im Ergebnis zu haben, negiert man die Tests:

        
      @ergebnis=grep !/1234$/,@liste;  
      @ergebnis=grep { !/1234$/ } @liste;  
      @ergebnis=grep { substr($_,-4) ne '1234' } @liste;  
      @ergebnis=grep { $_%10000!=1234 } @liste;  
      
      

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
  3. Moin!

    Sind denn regulaere Ausdruecke Pflicht? Ich finde den ganzen Ansatz hier unnoetig kompliziert. Wenn ich aus einer Menge von Werten genau 281100 und 381100 nicht haben will dann teste ich auf 281100 und 381100. Wenn sich Deine Menge aendern kann und spaeter mal auch 4-, 5-, 11-, 270-, ... 81100 auch nicht gewollt sind, dann frage ich nach right(). Ob letzteres in perl existiert weiss ich nicht, aber sicher wirds doch was aehnliches geben?

    --
    Signaturen sind blöd!