RegEx, URL bearbeiten
acid_ice
- perl
morsche,
ich habe mich gerade schon durchs archiv geschlagen, aber mir fehlt es wohl hinsichlich regulärer ausdrücke an der fähigkeit, diese auf andere problematiken zu übertragen.
daher hier eine kurze frage:
ich möchte in einer html datei alle verzeichnis- und linkangaben abändern, die relativ sind. mein ansatz war folgender:
$element =~ s/src="^http://"/src="$erweiterung$1"/gi;
ich will praktisch nur dort pfade ersetzen, wo kein http:// davor steht.
angewendet auf einen pfad z.b. ohne http:// wie folgender:
<img src="images/grafik.gif">
kommt das bei heraus (die variable $erweiterung enthält "../de/userpages/.."):
<img src="../de/userpages/./images/banner.gif" alt="" height="115" width="750">
da fehlt zum einen ein punkt vor dem images und zum anderen scheint mit die notation des regex auch nicht wirklich richtig zu sein, so dass es in manchen fällen zu ersetzungen kommt, wo dies eigentlich gar nicht passieren darf.
wenn ich den http zusatz aus dem regex rausnehme funktioniert er wunderbar, ersetzt nur eben auch die absoluten pfade, was nicht sein soll.
kann mir jemand helfen?
Hallo acid_ice,
[... relative Links aus Dokument filtern ...]
fuer dein Problem sind die Look-Ahead-Patterns wie geschaffen. Du
kannst dein Problem so loesen:
while($doc =~ m~href="(?!http://)([^"]+)"~g) {
print "URI: $1\n";
}
Das setzt aber vorraus, dass alle Links korrekt mit doppelten
Anfuehrungszeichen umgeben sind. Es bedarf allerdings nur kleiner
Aenderungen, um das zu korrigieren:
while($doc =~ m~href=(?:(["'])(?!http://)(.+?)\1))|(?:(?!http://)(\S+))~g) {
my $uri = $2 || $3;
print "URI: $uri\n";
}
Damit solltest du Links der Art href=../../abc, href="../../abc" und
href='../../abc' filtern koennen.
Grüße,
CK
Hi,
danke für die Antwort. Es funktioniert tatsächlich - für mein Vorhaben zwar nicht mit einer Schleife, aber es lässt sich einfach über einen erweiterten Ausdruck umsetzen.
Also - schönen Dank.
Kannst du mir das jetzt auch erkären, damit ich nicht nochmal fragen muss? ;)
Und wie siehts aus, wenn ich tatsächlich einmal mit Hilfe von $wert =~ s~asdf~asdfadsf~gi; etwas ersetzen will und im Suchbereich des Musters einen definitiven Ausschluss mit Hilfe von ^ vornehmen will? Also wie wäre da die Notation, wenn ich z.B. http:// aus den Ergebnissen herausfiltern will? [^http] geht ja nicht...
Hallo acid_ice,
Kannst du mir das jetzt auch erkären, damit ich nicht nochmal
fragen muss? ;)
Selbstverstaendlich.
m~href=(?:(["'])(?!http://)(.+?)\1))|(?:(?!http://)(\S+))~g
bedeutet ungefaehr:
»href=« gefolgt von
entweder
entweder " oder ' (speichere dies in einer Backreference),
gefolgt von nicht http:// (allerdings ist dieses Pattern
ein Zero-Width-Pattern, heisst, der Status bleibt erhalten und
der Match faehrt nach erfolgreichen »nicht http://« an derselben
Stelle fort, wo er aufgehoert hat) gefolgt von irgendwas bis zum
naechsten Zeichen, dass in der Backreference 1 steckt (\1)
(speichere das irgendwas in einer Backreference)
oder
nicht http:// (wieder als Zero-Width-Pattern) gefolgt von alles
ausser einem Whitespace.
Die (?:)-Klammern dienen nur der Gruppierung, das ?: verhindert, dass
diese Klammerung als Backreference gesehen wird.
Und wie siehts aus, wenn ich tatsächlich einmal mit Hilfe von
$wert =~ s~asdf~asdfadsf~gi; etwas ersetzen will und im
Suchbereich des Musters einen definitiven Ausschluss mit Hilfe
von ^ vornehmen will?
Eine negierte Klammer (also [^irgendwas]) ist eine negierte
_Zeichenklasse_, das bedeutet, [^http://] heisst soviel wie »Nicht h
oder nicht t oder nicht t oder nicht p oder nicht : oder nicht /
oder nicht /«.
Also wie wäre da die Notation, wenn ich z.B. http:// aus den
Ergebnissen herausfiltern will? [^http] geht ja nicht...
Das haengt davon ab, wie der Ausdruck aussieht. Eine Moeglichkeit
ist das von mir benannte »zero-width negative look-ahead pattern«.
Wie gesagt, das haengt davon ab, wie der Ausdruck insgesamt aussehen
soll.
Du musst dir klarmachen, dass ein regulaerer Ausdruck einen String
_beschreibt_. Wenn du also erst darueber nachdenkst, wie der String
aussehen darf (zuerst ruhig auch mit Worten und schriftlich, spaeter
mit genuegend Uebung wirst du das nicht mehr brauchen) und danach
dann das Pattern formulierst, wirst du kaum Probleme haben, den
richtigen Regex zu finden -- sofern das Problem ueberhaupt durch ein
Regex geloest werden kann.
Grüße,
CK