Micha: Für absolut reguläre Ausdrucks Experten!

Hi!

Ich habe folgenden geistreichen Text:
&onMond&Sterne sind oft zu sehen&off aber auch &ondie Sonne&off!

dieser soll umgewandelt werden in:
<Mond&Sterne sind oft zu sehen> aber auch <die Sonne>!

Also das &on zu < und das darauffolgende &off zu >. Das funktioniert auch wunderbar mit dem Ausdruck:
$text=~s/&on(.*?)&off/<$1>/ig; # ? für kleinst mögliche Lösung!

Und jetzt zu meiner Frage: Wieso funktioniert das mit folgendem Ausdruck nicht?
$text=~s/&on(.*(?!&off))&off/<$1>/ig;   # (?!...) ist ohne ...

Habe ich da irgendwie einen Denkfehler? Ich wäre echt sehr dankbar wenn mir jemand erklären könnte was ich falsch mache oder eine andere Lösung für mich hätte (ich verwende Perl 5).
Tschau
  Micha

Script zum testen:
#!/usr/bin/perl
$text='&onMond&Sterne sind oft zu sehen&off aber auch &ondie Sonne&off!';

$text=~s/&on(.*(?!&off))&off/<$1>/ig;
#$text=~s/&on(.*?)&off/<$1>/ig;   #damit funktioniert es

print "$1:$1\n";
print "$2:$2\n";
print "$&:$&\n\n";
print $text;

  1. hi!

    Und jetzt zu meiner Frage: Wieso funktioniert das mit folgendem Ausdruck nicht?
    $text=~s/&on(.*(?!&off))&off/<$1>/ig;   # (?!...) ist ohne ...

    Ich bin jetzt zu faul zum Überprüfen, deshalb nur eine ganz kurze Antwort: mit ".*(?!&off)" suchst du ja nach einer maximalen Anzahl von beliebigen Zeichen, in denen nicht &off vorkommt. Vielleicht liegt es daran.

    Allerdings weiß ich nicht, wieso du nicht die kürzere Methode verwenden willst, wenn sie funktioniert.

    bye, Frank!

    1. Hi Frank!

      Ich bin jetzt zu faul zum Überprüfen, deshalb nur eine ganz kurze Antwort: mit ".*(?!&off)" suchst du ja nach einer maximalen Anzahl von beliebigen Zeichen, in denen nicht &off vorkommt. Vielleicht liegt es daran.

      Allerdings weiß ich nicht, wieso du nicht die kürzere Methode verwenden willst, wenn sie funktioniert.

      Genau, könnte man meinen, daß man mit .*(?!off) nach einer maximalen Anzahl von beliebigen Zeichen, in denen nicht &off vorkommt, sucht - genau das will ich ja auch. Leider findet der reguläre Ausdruck aber kein einziges Zeichen, was mir absolut unverständlich ist.

      Logo, in diesem Falle könnte ich auch die kürzere Methode verwenden, in folgendem aber nicht mehr:
      $text=~s/&on(.*(?!Sonne))&off/<$1>/ig;
      In $& steht nun ein String in dem auch das Wort Sonne vorkommt. Check ich nicht!

      Hoffentlich hat noch jemand eine Lösung!
      Ciao
        Micha

  2. Hallo Micha!

    Und jetzt zu meiner Frage: Wieso funktioniert das mit folgendem Ausdruck nicht?
    $text=~s/&on(.*(?!&off))&off/<$1>/ig;   # (?!...) ist ohne ...

    Du suchst hier mit '(.*(?!&off))' nach einem Text, der an einer Stelle endet, auf die NICHT '&off' folgt. .* kann aber theoretisch schon ein paarmal &off enthalten. Nun kommt der Genickbruch:
    Auf diesen Text, dem kein &off folgt, soll nun &off folgen ...

    $text=~s/&on(.*(?!&sonne))&off/<$1>/ig;

    Wenn '.*' auf 'die Sonne' passt, endet dieser Text an einer Stelle, auf die NICHT 'sonne' folgt.

    Hoffe das hat die beim Hirnknoten lösen geholfen,
       Jörk