Hallo Sven,
Ziemlich lang, das Teil. Und leider erkennt es nicht, wenn man
eine IP-Adresse eingibt, weil du fest auf das Vorhandensein von
zwei oder mehr Buchstaben als TLD prüfst.
Und den Hauptbestandteil der Domain. Es ging hier auch nicht um IPs.
^(http://|ftp://|mailto:[a-zA-Z0-9._-]+@)?
Hier wird nach einem Protokoll gesucht. Ich habe einfach mal FTP,
HTTP und Emails definiert. Wenn es eine EMail ist, wird nach dem
Usernamen geschaut.
Fein. Eventuell haut dir der mailto-Teil ab, weil Usernamen eben
durchaus aus mehr als nur Zeichen, Zahlen, Punkt, Unterstrich und
Minus bestehen können.
laut RFC ja. In der Praxis eher nicht.
Irgendwie gibts auch die Variante, den Usernamen in
Anführungsstrichen mit beliebigen Zeichen (auch Leerzeichen)
anzugeben.
Ich glaube, Sven, du haettest die anderen Postings auch mal lesen
sollen ;-) Wir diskutieren hier ja nicht nur so zum Spass.
([A-Za-z0-9-]+.)*
Hier wird nach dem ersten Teil der Domain geschaut. Der darf *nur*
aus den Zeichen A-Za-z0-9 und einem Punkt bestehen und muss
wenigstens ein Zeichen lang sein. Er *muss* aber nicht matchen
(dafuer steht das * am Ende), es kann auch sein, dass wir direkt
zu der Domain kommen (z. B. http://wwwtech.de).
Wenn du den Punkt escapen würdest, würde er nicht für ein
beliebiges Zeichen stehen. :)
([A-Za-z0-9-]+.)*
Auch hier gilt: bitte die anderen Postings lesen. Der Ausdrucks-Teil
muss heissen:
([A-Za-z0-9.-]+.)*
Und ich zähle im Geiste mit: Teil 1 plus Punkt. Beliebig häufig,
und optional.
([A-Za-z0-9-]{3,}.)
Hiermit definiere ich den Hauptteil der Domain. Der muss aus
wenigstens 3 Zeichen der bekannten Zeichenklasse bestehen.
Wer behauptet, daß "Hauptteile von Domains" immer drei
Zeichen lang sein müssen?
Die gaengigen NICs
Die Denic fordert heute eine Mindestlänge von drei Zeichen,
es gibt aber auch 2-Zeichen-Domains
wie http://www.ix.de. Und unter .com sind
2-Zeichen-Domains auch möglich (wenngleich die wohl auch
alle schon registriert sind).
Stimmt, die habe ich nicht bedacht.
Geistiger Zähler: "teil1.teil1.tl2." Ein 3-Zeichen Teil zwingend.
([a-zA-Z0-9-]+.)*
Dem Haupt-Teil der Domain folgen weitere Teile. Sie alle muessen
aus der benannten Zeichenklasse bestehen.
Geistiger Zähler: "teil1.teil1.tl2.teilweise3.teilw3." Beliebig
viele weitere Bestandteile, auch optional.
([a-z]{2,})
Hiermit ist die Subdomain gemeint. Die muss aus wenigstens zwei
Zeichen bestehen.
Ein 2-Zeichen-Teil zwingend.
Geistiger Zähler: "teil1.teil1.tl2.teilweise3.teilw3.de"
Tja, das Ergebnis sieht nach einer gültigen Domain aus. Mir ist
zwar die Sache mit dem "Hauptteil der Domain" nicht klar, aber
irgendwie wird's schon matchen.
Der Hauptteil der Domain muss besondere Anforderungen erfuellen, und
er muss in *jedem* Fall vorhanden sein.
Man kann ja sogar Zahlen nehmen:
"123.123.123.123.de" geht. Nur ist das eben keine IP-Adresse.
Ja, das ist richtig. Das ist eine Schwachstelle meines RegEx.
Minimal muß eine Domain-Angabe sowas sein: "123.de"
Nein: 12a.de
Der Rest (Pfad, Query, Anker) ist ja eher ungefährlich
Noe, wenn schon validieren, dann richtig validieren.
(obwohl ich beim Query-String auch Großbuchstaben zulassen würde, »» rein instinktiv).
Jap. Ein Fehler. Ich sollte mehr schlafen, die letzte Nacht habe ich
gar nicht geschlafen.
Wie repariert man das jetzt? Eine zweite Verzweigungsvariante für
IP-Adressen einbauen.
IP-Adressen sind so relativ leicht erkennbar:
(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})
So validierst du allerdings keine IP-Adressen.
Die Zwangslänge der Second-Level-Domain würde ich einfach auf 2
Zeichen senken (1 Zeichen ist IIRC wirklich verboten), und danach
keine weiteren Bestandteile mehr zulassen, nur noch davor.
Also:
!^(http://|ftp://|mailto:[a-zA-Z0-9._-]+@)?((\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})|([A-Za-z0-9-]+.)*([A-Za-z0-9-]{2,}.)([a-z]{2,}))(/[a-zA-Z%0-9]*)*(?[a-z%0-9&;+=,]*)?(#.*)?$!
Sieht für mich irgendwie schöner aus.
Was noch fehlt: Wenn kein http-ftp-mailto angegeben wird, wird das
auch nicht in den Link eingebaut.
Habe ich ja geschrieben. Das kann man sehr einfach ueber /e einbauen.
Ich habs nur einfach nicht getan, damit Martin auch noch denkt. In
meiner Perl-Version ist das natuerlich eingebaut ;-)
Sowas ist böse, weil es natürlich nicht funktioniert.
Und das wird man kaum mit einem regulären Ausdruck durch
Suchen/Ersetzen regeln können, sondern da muß weitere
Programmlogik her.
Noe.
preg_match ('!^(http://|ftp://|mailto:[a-zA-Z0-9._-]+@)?((\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})|([A-Za-z0-9-]+.)*([A-Za-z0-9-]{2,}.)([a-z]{2,}))(/[a-zA-Z%0-9]*)*(?[a-z%0-9&;+=,]*)?(#.*)?$!',$text,$gefunden);
Der RegEx ist Buggy, wegen des |.
Im Array $gefunden stehen jetzt alle Klammerausdrücke, die der
reguläre Ausdruck so produziert hat. Mit If-Abfragen und etwas
Raten kann man fehlende Informationen hinzufügen und in einen
schönen Link verwandeln. :)
Iwo. Das geht mit einem RegEx.
Also, meine debuggte Version:
preg_replace('!(:?(:?(http://|ftp://|mailto:[a-zA-Z0-9._-]+@)*([a-zA-Z0-9.-]+.)?([A-Za-z0-9-]{3,}.)([a-zA-Z0-9-]+.)*([a-z]{2,}))|(:?((\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})))(/[a-zA-Z%0-9]*)*(?[a-zA-Z%0-9&;+=,]*)?(#.*)?!e','"<a href="".("$6" ? "$6" : (($1 ? "$1" : 'http://)."$2$3$4$5")."$7$8$9">$1$2$3$4$5$6$7$8</a>"',$text)
Das ist leider ungetestet und koennte kleinere Fehler im e-Teil
haben.
Gruesse,
C'Klammerkoenig'K