2012-06-03 22 views
8

Sto utilizzando una funzione PHP per trasformare automaticamente gli URL in una stringa di testo in un collegamento reale su cui le persone possono fare clic. Sembra funzionare nella maggior parte dei casi, tuttavia ho trovato alcuni casi in cui non è così.Espressione regolare collegamento automatico

Non capisco davvero le espressioni regolari, quindi speravo che qualcuno potesse darmi una mano con questo.

Qui è il modello Attualmente sto usando:

$pattern = "/(((http[s]?:\/\/)|(www\.))(([a-z][-a-z0-9]+\.)?[a-z][-a-z0-9]+\.[a-z]+(\.[a-z]{2,2})?)\/?[a-z0-9.,_\/~#&=;%+?-]+[a-z0-9\/#=?]{1,1})/is"; 

tuttavia ecco alcuni link che ho trovato che questo modello non corrisponde:

  • www.oakvilletransit.ca - Non è sicuro , ma supponendo che non corrisponda a causa del codice paese di due lettere
  • www.grt.ca - Un altro con il dominio .ca che non funziona
  • Diversi altri .ca a ddresses
  • freepublictransports.com - Indirizzi senza www. o http: // davanti a loro. Vorrei che anche questi funzionassero.
  • www.222tips.com - Supponendo che non corrisponda a causa dei numeri all'inizio dell'indirizzo.

Qualcuno sa come posso modificare il modello di regex in modo che corrisponda anche a questi casi?

EDIT - Si deve anche corrispondere gli URL che possono avere un punto alla fine. Se un URL è l'ultima parte di una frase, potrebbe esserci un periodo alla fine che non dovrebbe essere incluso nel link effettivo. Attualmente questo modello tiene conto anche di questo.

EDIT 2 - Sto usando il modello come questo:

$pattern = "/((http|https):\/\/)?([a-z0-9-]+\.)?[a-z][a-z0-9-]+(\.[a-z]{2,6}){1,3}(\/[a-z0-9.,_\/~#&=;%+?-]*)?/is"; 
    $string = preg_replace($pattern, " <a target='_blank' href='$1'>$1</a>", $string); 
    // fix URLs without protocols 
    $string = preg_replace("/href='www/", "href='http://www", $string); 
    return $string; 
+0

punta Regex: '[s]' non è necessario?. Basta usare 's?'. – Ryan

+0

Consiglio regex: '{1,1}' non ha alcun senso. Neanche '{2,2}'. – Ryan

+0

Ok, ho trovato questo codice su un'altra domanda SO. Quindi cambiando [s]? a s? e rimuovere {1,1} e {2,2} non dovrebbe fare la differenza? –

risposta

5

La seguente espressione regolare corrisponderà URL:

  • (opzionalmente) con http:// o https://
  • (opzionale) Con un sottodominio (www.example.com, , ecc.)
  • con 1-3 estensioni di dominio, che ognuno deve essere 2-6 caratteri (www.example.com.gu, www.example.com.au.museum, ecc)
  • (opzionalmente) con una barra alla fine
  • (opzionale) Con i caratteri validi dopo la barra

il /i alla fine rende caso insensitive.

/((http|https):\/\/)?([a-z0-9-]+\.)?[a-z0-9-]+(\.[a-z]{2,6}){1,3}(\/[a-z0-9.,_\/~#&=;%+?-]*)?/is

Edit: Questo non corrisponderà alcun "appeso" periodi alla fine (come ad esempio la fine di una frase) perché non è parte dell'URL, e non dovrebbe essere incluso nel href attributo del tuo link.

Edit 2: Nella tua prima preg_replace(), cambiare $1 a $0. Questo inserirà l'intera stringa abbinata invece di una singola parte di essa.

Edit 3: (Update 2) Ecco un modo migliore è possibile verificare la presenza di un http:// o https:// all'inizio:

preg_replace("/href='[^h][^t][^t][^p][^s]?[^:]/", "/href='http:\/\/", $string); 
+0

((http | https): //) dovrebbe essere ((http | https): \/\ /) Ho iniziato a usare un # invece di un '/' come delimitatore quando si gestiscono gli URL, quindi non si ' Devono sfuggire alle barre in avanti. E il/i rende il caso INsensibile. – Sp4cecat

+1

Derp. Fatto questo su regexbuddy, ho dimenticato di sfuggire a quei due. Aggiornamento della risposta, grazie. __Modo: __ Non ho mai saputo che potresti usare caratteri diversi per delimitatori! È bello saperlo, grazie. – Litty

+0

Per qualche motivo quando spengo lo schema che ho per questo i collegamenti non vengono visualizzati, anche l'URL di testo semplice scompare nel testo. –

3

ho avuto problemi con tutti gli esempi di cui sopra.

Ecco quello che funziona:

function autolink($string){ 
     $string= preg_replace("#http://([\S]+?)#Uis", '<a href="http://\\1">\\1</a>', $string); 
     return $string; 
}