2011-08-07 6 views
0

J'ai cette regex qui fonctionne très bien mais pas dans tous les scénarios, par exemple si j'ai une longue url dire "http://www.gob.cl/especiales/politicas-y-propuestas-de -accion-para-el-desarrollo-de-la-educacion-chilena/"il me rendra seulement" http: //www.gob. " dans le cadre de l'urlRegex pour analyser les longues URL

Voici mon code

 
    $regexUrl = "((https?|ftp)\:\/\/)?"; // SCHEME 
    $regexUrl .= "([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)[email protected])?"; // User and Pass 
    $regexUrl .= "([a-zA-Z0-9-]+)\.([a-zA-Z]{2,3})"; // Host or IP 
    $regexUrl .= "(\:[0-9]{2,5})?"; // Port 
    $regexUrl .= "(\/([a-zA-Z0-9+\$_-]\.?)+)*\/?"; // Path 
    $regexUrl .= "(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:@&%=+\/\$_.-]*)?"; // GET Query 
    $regexUrl .= "(#[a-zA-Z_.-][a-zA-Z0-9+\$_.-]*)?"; // Anchor 
    //if(preg_match_all("#\bhttps?://[^\s()]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#", $message, $matches1, PREG_PATTERN_ORDER)) 
    //$pattern = '/((https?|ftp)\:(\/\/)|(file\:\/{2,3}))?(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(((([a-zA-Z0-9]+)(\.)?)+)(\.)(com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|[a-z]{2}))([\/][\/a-zA-Z0-9\.]*)*([\/]?(([\?][a-zA-Z0-9]+[\=][a-zA-Z0-9\%\(\)]*)([\&][a-zA-Z0-9]+[\=][a-zA-Z0-9\%\(\)]*)*))?/'; 
    if(preg_match_all("/$regexUrl/", $urlMessage, $matches1, PREG_PATTERN_ORDER)) 
    { 
     try 
     { 
      foreach($matches1[0] as $urlToTrim1) 
      { 
       $url= $urlToTrim1; 
       echo $url; 
      } 
     } 
     catch(Exception $e) 
     { 
      $url="-1"; 
     } 
    } 

il y avoir une expression rationnelle générique qui peut analyser toutes sortes de urls.

Répondre

2

Votre hôte ou IP partie du regex

"([a-zA-Z0-9-]+)\.([a-zA-Z]{2,3})" 

ne permet à un maximum d'un seul point à l'intérieur. Par conséquent, "www.xyz.com" ne peut jamais correspondre.

Je ne sais pas ce que vos besoins spécifiques, mais vous pouvez aller avec quelque chose comme

"([^/?#:]+)" 

pour la partie hôte.

-1

Que diriez-vous que vous correspondez tout en commençant par http: // ou https: //

((?:http|https)(?::\\/{2}[\\w]+)(?:[\\/|\\.]?)(?:[^\\s"]*))

+0

pourquoi cette baisse voté par curiosité? – Chamilyan

+0

(1) '(?: Http | https)' est inutilement prolixe et inefficace; 'https?' fonctionne très bien. (2) '/' n'a besoin d'être échappé que si vous utilisez '/' comme délimiteur de regex; il y a beaucoup d'autres options. (3) L'échappement double n'est pas nécessaire si vous utilisez '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '. pas un opérateur "OR", il correspond juste à un | | '(le" OU "est implicite). (5)' [/.]? 'est inutile de toute façon, puisque' [^ \ s "] *' correspond à la fois personnages. (6) Il n'est pas nécessaire d'envelopper toute la regex dans '()'. (...) Je pourrais continuer ...;) –

+0

Ouais mais ça marche;) tout va bien. – Chamilyan

1

Voici mon seul pour extraire toutes les URL de texte $:

preg_match_all('#(https?://[a-z0-9\.\-_\#%&=/?;,!:[email protected]\$\+]+)#iu', $text, $m); 

Il est sur l'hypothèse qu'une URL commence par https: // ou http: // et peut ensuite avoir une séquence limitée à un ensemble spécial de caractères.

Ensuite, je peux utiliser http://www.php.net/manual/en/function.parse-url.php sur $m pour obtenir tous les détails de l'URL

Edit: En outre, si vous parsing, vous pouvez vérifier les périodes (.) et autres signes de ponctuation à la fin de l'URL . J'ai remarqué que les humains peuvent mettre un . à la fin de l'URL si l'URL est à la fin de la phrase par exemple comme http://example.com.

donc je fais quelque chose comme ceci:

if (($url[$pos]==='!') || ($url[$pos]==='.')) { // probably do not want these chars at the end of a url! 
    $url = substr($url, 0, $pos); 
} 
+0

+1. Vous pouvez également utiliser un lookbehind pour forcer la regex elle-même à reculer si le dernier caractère correspondant est l'un des caractères interdits: ''#https?: // [a-z0-9 ._ \ #% &=/?;,!: ~ @ $ + -] + (?