Norbert Kölln: Zeilen aus Text löschen, die bestimmten String nicht beinhalten

Moin, moin, liebe SELFHTML-Gemeinde!

Ich habe in einer Variablen einen mehrzeiligen Text, der garantiert mit einem Zeilenumbruch beginnt und endet, z. B.
  $text="\nCEGVZTKGF\nEGJIOJ\nJKIOH\nJIOJIO\nDFRTDEG\nZGFZUGFF\nHJUIOHUI\n";

In einer zweiten Variablen steht ein mich interessierender String, z. B.
  $relevant="EG";

Es ist kein Problem, alle Textzeilen zu löschen, die den String in $relevant enthalten:
  $text=~s/\n[^\n]*$relevant[^\n]*//g;

Ich möchte aber genau das Gegenteil erreichen: Ein regulärer Ausdruck soll dafür sorgen, daß nur noch die Zeilen übrigbleiben, die "EG" enthalten.

Wer hat einen Tip für mich? In SELFHTML und an anderen Stellen habe ich keine passenden Beispiele gefunden und auch die PERL-Doku (z. B. perlre) hat mir keinen Geistesblitz verschafft.

Mit freundlichem Gruß und bestem Dank im Voraus,
Norbert Kölln

  1. MoiN!

    Es ist kein Problem, alle Textzeilen zu löschen, die den String in $relevant enthalten:
      $text=~s/\n[^\n]*$relevant[^\n]*//g;

    Dann solltest du mit dem regulären Ausdruck einfach nur suchen, statt ersetzen.

    if ($text=~/\n([^\n]*$relevant[^\n]*)/)
    {
      $gefunden = $1;
    }

    - Sven Rautenberg

    1. Hallo Sven!

      Leider habe ich mit Deiner Lösung noch immer nicht alle relevanten Zeilen in der Variablen $text.

      Hast Du nicht doch eine Variante, die die nicht-relevanten Zeilen löscht?

      Norbert

      PS: Ich bin in Hamburg mit einem Sven Rautenberg zur Schule gegangen. Kannst Du das sein?

      1. MoiN, Norbert!

        Leider habe ich mit Deiner Lösung noch immer nicht alle relevanten Zeilen in der Variablen $text.

        Nein, aber in der Variablen $gefunden steht doch was drin, oder?

        Das Prinzip ist, daß das Suchmuster, welches gefunden werden soll, in runden Klammern steht und dadurch der Variablen $1 übergeben wird.

        Wenn du mehrere Zeilen mit dem relevanten Text hast, mußt du einfach mehrfach suchen. Es gibt auch einen Array-Kontext für den regulären Ausdruck, so in der Art:

        @relevantes ($text =~ /\n([^\n]*$relevant[^\n]*)/g);

        Der liefert alle Suchtreffer ins Array.

        Hast Du nicht doch eine Variante, die die nicht-relevanten Zeilen löscht?

        Kombinieren geht über studieren. :)

        PS: Ich bin in Hamburg mit einem Sven Rautenberg zur Schule gegangen. Kannst Du das sein?

        Ich bin mit keinem Norbert Kölln zur Schule gegangen, also: Nein, eher nicht.

        - Sven Rautenberg

  2. use Mosche;

    Ich habe in einer Variablen einen mehrzeiligen Text, der garantiert mit einem Zeilenumbruch beginnt und endet, z. B.
      $text="\nCEGVZTKGF\nEGJIOJ\nJKIOH\nJIOJIO\nDFRTDEG\nZGFZUGFF\nHJUIOHUI\n";

    In einer zweiten Variablen steht ein mich interessierender String, z. B.
      $relevant="EG";

    Es ist kein Problem, alle Textzeilen zu löschen, die den String in $relevant enthalten:
      $text=~s/\n[^\n]*$relevant[^\n]*//g;

    Ich möchte aber genau das Gegenteil erreichen: Ein regulärer Ausdruck soll dafür sorgen, daß nur noch die Zeilen übrigbleiben, die "EG" enthalten.

    Ein grundsätzlich anderer Ansatz wäre sowas wie:
    my @tmp;
    foreach (split(/\n/, $text)) {
     push @tmp, $_ if /$relevant/;
    }
    $text = join "\n", @tmp;

    oder, als einzeiler
    $text = join ("\n", grep { /$relevant/ } split(/\n/, $text));

    das sieht außerdem *geil* aus, und versteht keiner mehr 8-)

    use Tschoe qw(Matti);

    1. Hallo Matti!

      Die zweite Lösung gefällt mir - und funktioniert. Ich werde mich mal damit beschäftigen, um sie auch zu verstehen. Vielen Dank!

      Trotzdem noch einmal die Frage: Gibt es einen regulären Ausdruck, der dasselbe mit s/// macht?

      Norbert

      1. Hallo Matti!

        Die zweite Lösung gefällt mir - und funktioniert. Ich werde mich mal damit beschäftigen, um sie auch zu verstehen. Vielen Dank!

        He, da kann ich noch über:

        $text = join ("\n",($text =~ /\n([^\n]*$relevant[^\n]*)/g ));

        Ungetestet, kryptisch und ohne Garantie, aber IMO sieht das ganz gut aus. :)

        Wenn vorne und hinten auch noch Newlines ransollen:
        $text = "\n" . join ("\n",($text =~ /\n([^\n]*$relevant[^\n]*)/g )) . "\n";

        - Sven Rautenberg