2012-03-28 7 views
1

Ich brauche eine Funktion, die nach vorhandenen URLs in einer Zeichenfolge sucht.Regex regulärer Ausdruck, um die meisten URLs zu entsprechen, muss verbessert werden

function linkcleaner($url) { 
$regex="(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))"; 

if(preg_match($regex, $url, $matches)) { 
echo $matches[0]; 
} 
} 

Der reguläre Ausdruck wird von der John Gruber's blog, wo er das Problem der Schaffung einer Regex alle URLs passende gerichtet. Leider kann ich es nicht funktionieren lassen. Es scheint, dass das Problem von den Anführungszeichen in der Regex oder den anderen Punktsymbolen am Ende des Ausdrucks kommt. Jede Hilfe wird geschätzt. Vielen Dank!

+10

„Kann nicht damit es funktioniert "ist kein integrierter PHP-Fehler Botschaft. –

+2

@JackManey, roflmao –

+0

Sorry, der Fehler war "Parse Fehler: Syntaxfehler, unerwartet ',' in C: \ ... \ config.php on line ...". Englisch ist nicht meine Muttersprache, manchmal habe ich Probleme zu erklären, was ich sagen möchte. – olegb3

Antwort

2

Abgesehen von @ Tandus Antwort benötigen Sie auch Trennzeichen für eine Regex in PHP.

Die einfachste wäre Ihr Muster mit einem # zu beginnen und enden wie das Zeichen, das nicht in es scheint:

$regex="#(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’]))#"; 
+0

"#" bearbeitet werden kann Teil der URL (Bezeichnung Anker) ... – poncha

+0

danke! Wie könnte ich das vermissen ... gerettet meinen Tag :) – olegb3

+0

@ponacha Es erscheint nicht in diesem Regex-Muster und das ist das einzige, was hier zählt. – jeroen

3

Sie müssen die " mit einem \

1

Jack Maneys Kommentar ... EPIC entkommen: D

Auf eine ernstere Note, es funktioniert nicht, weil Sie die Stringliteral direkt in der Mitte beendet .

Um ein doppeltes Anführungszeichen (") in einem String enthalten, müssen Sie es entkommen ein \

mit So wird die Linie

$regex="/(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’]))/"; 

Hinweis Ich habe entkam die (') auch. Das ist, wenn Sie eine Zeichenfolge zwischen 2 einfachen Anführungszeichen definieren.

+0

Vielen Dank & @tandu Ich erhalte immer noch einen Fehler Warnung: preg_match() [Funktion.preg-match]: Unbekannter Modifikator '\' in C: \ wamp \ www \ ... \ config.php in Zeile 919 – olegb3

+0

I Denken Sie in PHP müssen Sie die Regex durch das gleiche Zeichen am Anfang und am Ende abgrenzen. Ich habe meine Antwort zum Abgrenzen mit '/' –

1

Ich bin nicht sicher, wie ihr diese regex lesen, weil es ein echten Schmerzen sind zu lesen/ändern ...;)

dies versuchen (das ist kein Einzeiler, ja, aber es ist leicht zu verstehen und zu ändern, wenn nötig):

<?php 
$re_proto = "(?:https?|ftp|gopher|irc|whateverprotoyoulike)://"; 
$re_ipv4_segment = "[12]?[0-9]{1,2}"; 
$re_ipv4 = "(?:{$re_ipv4_segment}[.]){3}".$re_ipv4_segment; 
$re_hostname = "[a-z0-9_]+(?:[.-][a-z0-9_]+){0,}"; 
$re_hostname_fqdn = "[a-z0-9_](?:[a-z0-9_-]*[.][a-z0-9]+){1,}"; 
$re_host = "(?:{$re_ipv4}|{$re_hostname})"; 
$re_host_fqdn = "(?:{$re_ipv4}|{$re_hostname_fqdn})"; 
$re_port = ":[0-9]+"; 
$re_uri = "(?:/[a-z0-9_.%-]*){0,}"; 
$re_querystring = "[?][a-z0-9_.%&=-]*"; 
$re_anchor = "#[a-z0-9_.%-]*"; 
$re_url = "(?:(?:{$re_proto})(?:{$re_host})|{$re_host_fqdn})(?:{$re_port})?(?:{$re_uri})?(?:{$re_querystring})?(?:{$re_anchor})?"; 

$text = <<<TEXT 
http://www.example.com 
http://www.example.com/some/path/to/file.php?f1=v1&f2=v2#foo 
http://localhost.localdomain/ 
http://localhost/docs/??? 
www....wwhat? 
www.example.com 
ftp://ftp.mozilla.org/pub/firefox/latest/ 
Some new Mary-Kate Olsen pictures I found: the splendor of the Steiner Street Picture of href… http://t.co/tJ2NJjnf 
TEXT; 

$count = preg_match_all("\01{$re_url}\01is", $text, $matches); 
var_dump($count); 
var_dump($matches); 
?> 
+0

Ihre Antwort ist groß! Es ist die einzige Regex, die die folgende Zeichenfolge korrekt analysiert: 'RT @JustBrelieve:" @ enn4xor: #TBT Letzten Sommer. * _ * http://t.co/LsasKwfe"you süß, du süß.' – Oleg

+0

Ich habe einige Probleme' $ re_hostname_fqdn' Parameter gefunden. Es passt "Mary-Kate" als URL in 'Einige neue Mary-Kate Olsen Bilder, die ich fand: die Pracht der Steiner Street Bild von href ... http: // t.co/tJ2NJjnf' – Oleg

+0

@Oleg' $ re_hostname_fqdn' würde übereinstimmen 'Mary-Kate', weil es ein wahrscheinlicher Hostname ist (wie jedes Wort ...), aber warum passt es nicht zu Proto .. ich werde das hier sehen, danke, dass du es bemerkt hast – poncha