Steve Baumann: Negation von Patterns

Hallo,
ich bin auf der Suche nach einer Moeglichkeit, aus einer Liste von verschiedenen Dateinamen, alle diejenigen herauszufinden, die nicht auf eine bestimmte Endung matchen.

Beispielsweise lese ich als erstes eine HTML-Datei in einen String:

#######################################################
open(INPUT,"c:\info.html") or die "$! Can't open ...";
  while (<INPUT>) {$html .= $_;}
close INPUT;
#######################################################

Anschliessend moechte ich alle verlinkten Images daraus haben, die auf die Endung .gif enden (und noch mit /fb beginnen (nebensaechlich)):

#######################################################
$html =~ s/<img.*src="(/fb[\S|.]*(gif))"/push (@v,$1);/egmi;
#######################################################

Soweit ist alles ok, aber nun moechte ich alle, in dieser Art verlinkten Dateien, welche nicht die Endung .gif haben.

Wie kriege ich das hin? Weis jemand Rat?

Danke
Gruss, Steve

  1. Hallo Steve,

    Soweit ist alles ok, aber nun moechte ich alle, in dieser Art verlinkten Dateien, welche nicht die Endung .gif haben.

    Verneinen kann man meines Wissens bei regulaeren Ausdruecken nur einzelne Zeichen bzw. Zeichengruppen. Eine Moeglichkeit bestehend aus zwei Statements ist es, zunaechst mal alle <img>-Tags mittels RegExpr in einen Array zu extrahieren, und diesen dann mit Hilfe der grep-Funktion so zu filtern, dass nur noch Elemente mit der Bedingung ".gif" uebrig bleiben. Zur grep-Funktion siehe http://selfhtml.teamone.de/cgiperl/funktionen/listenhashes.htm#grep

    viele Gruesse
      Stefan Muenz

  2. Gude Steve,

    #######################################################
    $html =~ s/<img.*src="(/fb[\S|.]*(gif))"/push (@v,$1);/egmi;
    #######################################################

    Soweit ist alles ok, aber nun moechte ich alle, in dieser Art verlinkten Dateien, welche nicht die Endung .gif haben.

    HTML solltest du immer mit Hilfe von HTML::Parser o.ä. parsen; auf diese Weise verarbeitest du das HTML nicht nur ordentlich, sondern du kommst auch sehr bequem an die einzelnen Dateinamen heran - ohne auf das HTML drumherum achten zu müssen.

    Ein Beispiel:

    #!/usr/bin/perl -w
    use strict;
    use HTML::Parser;

    my $parser = MyParser->new();
    $parser->parse_file('path/to/filename');

    package MyParser;
    use base qw(HTML::Parser);

    sub start
    {
       my (undef, $tag, $attr) = @_;
       if ($tag eq 'img') {print $attr->{src}};
    }

    perldoc HTML::Parser

    Zu deiner ursprünglichen Frage:

    Du könntest die RegExp aufteilen:
    push @non_gif, $filename if $filename =~ m(^/fb) && $filename !~ /gif$/;
    oder: "negative look-behind assertion" verwenden.
    push @non_gif, $filename if $filename =~ m|^/fb.*(?<!gif)$|;

    perldoc perlre

    Eine Lösung lässt sich allerdings auch "nur" mit substr finden.
    perldoc -f substr

    ad,
    kd.