Vai al contenuto

Regex: Espressioni regolari in PHP, parte 3

Negli articoli precedenti abbiamo visto come utilizzare le espressioni regolari (regex) per trovare, identificare o sostituire il testo, le parole o qualsiasi tipo di caratteri. In questo articolo, ho segnalato alcune espressioni regolari estremamente utili che ogni sviluppatore dovrebbe avere nel suo toolkit.

Per molti principianti, le espressioni regolari possono sembrare difficile da imparare e da usare. In realtà, sono molto meno difficili di quanto si pensi. Ricapitoliamo la sintassi di base già ampiamente vista negli articoli precedenti:

Espressione regolare Corrisponde a
pippo La stringa “pippo”
^pippo “pippo” all’inizio di una stringa
pippo$ “pippo” alla fine di una stringa
^pippo$ “pippo” quando è da solo su una stringa
[abc] a, b, oppure c
[a-z] Qualsiasi lettera minuscola (una sola)
[^A-Z] Qualsiasi carattere che non è una lettera maiuscola (una sola)
(gif|jpg) Corrisponde a “gif” o “jpeg”
[a-z]+ Una o più lettere minuscole
[0-9.-] Qualsiasi cifra da 0 a 9, punto o trattino
^[A-zA-Z0-9_]{1,}$ Qualsiasi parola di almeno una lettera, numero o underscore
([wx])([yz]) wy, wz, xy oppure xz
[^A-Za-z0-9] Qualsiasi simbolo (che non sia un numero o una lettera)
([A-Z]{3}|[0-9]{4}) Corrisponde a tre lettere o quattro numeri

 

Convalida nome di dominio

Verifica se una stringa è un nome di dominio valido.

$url = "http://www.gianlucatramontana.com/";
if (preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $url)) {
    echo "Url corretto.";
} else {
    echo "Url errato.";
}

Evidenzia una parola in un testo

Trova una parola specifica in un testo e la evidenzia. Estremamente utile nei risultati di ricerca.

//Highlight a word in the content
$text = "Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura
ché la diritta via era smarrita. Ahi quanto a dir qual era è cosa dura esta selva selvaggia e aspra e forte che nel pensier rinova la paura!";
$text = preg_replace("/\b(selva)\b/i", '<span style="background:#5fc9f6">\1</span>', $text);
echo $text;

Evidenziare i risultati di ricerca in un blog WordPress

Ottimo metodo per implementare il codice sopra in un blog WordPress.  Apri il file search.php e trova la funzione the_title(). Sostituiscilo con il seguente:

echo $title;

Ora, appena prima della riga modificata, aggiungi questo codice:

<?php
	$title 	= get_the_title();
	$keys= explode(" ",$s);
	$title 	= preg_replace('/('.implode('|', $keys) .')/iu',
		'<strong>\0</strong>',
		$title);
?>

Salva il file search.php e apri style.css. Aggiungi alla fine questa riga di codice:

strong.search-excerpt { background: yellow; }

Ricevi tutte le immagini da un documento HTML

Se hai sempre sognato di estrarre tutte le immagini da una pagina web, questo è il codice che fa per te.  Lo script estrae tutti i link delle immagini. Poi con la libreria cURL si può estendere questo script per effettuare il download delle immagini.

$data = '<p style="text-align: center;"><a href="https://www.gianlucatramontana.it/wp-content/uploads/2014/02/400px-NFAexample.svg_.png" data-slb-group="334" data-slb-active="1" data-slb-internal="0"><img class="alignnone  wp-image-339 aligncenter" style="width: 200px; height: 190px;" alt="400px-NFAexample.svg" src="https://www.gianlucatramontana.it/wp-content/uploads/2014/02/400px-NFAexample.svg_.png" width="400" height="368"></a></p><p><a href="https://www.gianlucatramontana.it/wp-content/uploads/2014/02/regex-example.png" data-slb-group="334" data-slb-active="1" data-slb-internal="0"><img class="alignnone  wp-image-338 aligncenter" style="width: 400px; height: 150px;" alt="regex-example" src="https://www.gianlucatramontana.it/wp-content/uploads/2014/02/regex-example.png" width="931" height="346"></a></p>';

$images = array();
preg_match_all('/(img|src)=("|\')[^"\'>]+/i', $data, $media);
unset($data);
$data=preg_replace('/(img|src)("|\'|="|=\')(.*)/i',"$3",$media[0]);
foreach($data as $url)
{
	$info = pathinfo($url);
	if (isset($info['extension']))
	{
		if (($info['extension'] == 'jpg') ||
		($info['extension'] == 'jpeg') ||
		($info['extension'] == 'gif') ||
		($info['extension'] == 'png'))
		array_push($images, $url);
	}
}

print_r($images);

Rimuovere parole ripetute (case insensitive)

Spesso le parole si ripetono durante la digitazione? Questo pratico regexp sarà molto utile.

$text = "questo script script potrebbe essere di grande grande utilità";
$text = preg_replace("/\b(\w+)\s+\\1\b/i", "$1", $text);
echo($text);

Rimuovere la punteggiatura ripetuta

Come sopra, ma con la punteggiatura. Addio ai punti ripetuti!

$text = "hello, world..";
$text = preg_replace("/\.+/i", ".", $text); 
echo($text);

Trova le corrispondenze di un tag XML/HTML

Questa funzione ha due parametri in ingresso. Il primo è il tag da cercare, il secondo è il codice HTML o XML. La funzione restituisce un array con tutti i valori contenuti nel tag specificato.

function get_tag( $tag, $xml ) {
  $tag = preg_quote($tag);
  preg_match_all('/<'.$tag.'[^>]*>(.*?)<\/'.$tag.'>/',
                   $xml,
                   $matches,
                   PREG_PATTERN_ORDER);

  return $matches[1];
}

$html_source = "<div>Test DIV1</div><p>Test P1</p><div>Test DIV2</div><p>Test P2</p>";

print_r(get_tag("p", $html_source));

Trova le corrispondenze di un tag XML/HTML con un attributo specifico

Questa funzione è simile alla precedente, ma permette di trovare le corrispondenze di quei tag con un attributo specifico. Per esempio “<div id=”header”>”.

function get_tag( $attr, $value, $xml, $tag=null ) {
  if( is_null($tag) )
    $tag = '\w+';
  else
    $tag = preg_quote($tag);

  $attr = preg_quote($attr);
  $value = preg_quote($value);

  $tag_regex = "/<(" . $tag . ")[^>]*" . $attr . "\s*=\s*(['\"])" . $value . "\\2[^>]*>(.*?)<\/\\1>/";

  preg_match_all($tag_regex,
                 $xml,
                 $matches,
                 PREG_PATTERN_ORDER);

  return $matches[3];
}

$html_source = "<div id='block'>Test DIV</div><p>Test P</p><div>Test DIV</div><p>Test P1</p>";

print_r(get_tag("id", "block", $html_source, "div"));

Verifica la correttezza del codice esadecimale di un colore

Altra interessante funzione per gli sviluppatori. Verifica la corretta sintassi di un colore esadecimale.

$string = "#555555";
if(preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $string)) { 
	echo "$string: Codice colore esatto<br /><br />";
}
else {
	echo "$string: Codice colore errato<br /><br />";
}

$string1 = "#55G555";
if(preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $string1)) { 
	echo "$string1: Codice colore esatto<br /><br />";
}
else {
	echo "$string1: Codice colore errato<br /><br />";
}

Trova il titolo della pagina

Questo script trova e stampa il testo che sta all’interno del tag <title> di una pagina html.

$fp = fopen("http://www.gianlucatramontana.it","r"); 
while (!feof($fp) ){
    $page .= fgets($fp, 4096);
}

$titre = eregi("<title>(.*)</title>",$page,$regs); 
echo $regs[1];
fclose($fp);

Controlla la correttezza delle date

Molti sviluppatori hanno da sempre la necessità di controllare il formato delle date in input. L’esempio controlla solo il formato della data in input, mentre non controlla la validità della data. Infatti accetta la data 31/02/2014 che è semanticamente sbagliata. Inoltre accetta trattini, backslash, spazi e punti come separatori della data. Per cui 01-01-2014 è valido come 01.01.2014 e 01/01/2014.

//Formato d/m/yy e dd/mm/yyyy
//da 1/1/00 a 31/12/99 e da 01/01/1900 a 31/12/2099

$txt = "01/01/2014";
$pattern = '/\b(0?[1-9]|[12][0-9]|3[01])[- \/.](0?[1-9]|1[012])[- \/.](19|20)?[0-9]{2}\b/';
if (preg_match($pattern, $txt)) {
    echo "corretto.";
} else {
    echo "errato.";
}

//Formato dd/mm/yyyy
//da 01/01/1900 a 31/12/2099
$pattern = '/(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.](19|20)[0-9]{2}/';

//Formato m/d/y and mm/dd/yyyy
//da 1/1/99 a 12/31/99 e da 01/01/1900 a 12/31/2099
$pattern = '/\b(0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])[- \/.](19|20)?[0-9]{2}\b/';

//Formato mm/dd/yyyy
//da 01/01/1900 a 12/31/2099
$pattern = '/(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)[0-9]{2}/';

//Formato yy-m-d or yyyy-mm-dd
//da 00-1-1 a 99-12-31 e da 1900-01-01 a 2099-12-31
$pattern = '\b(19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])\b';

//Formato yyyy-mm-dd
//da 1900-01-01 a 2099-12-31
$pattern = '(19|20)[0-9]{2}[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])';

 Controlla la validità del codice HTML

//commento
$pattern = '/<!--.*?-->/';

//HTML file
//Convalida un file HTML completo.
//Performance will be terrible on HTML files that miss some of the tags 
//(and thus won't be matched by this regular expression).  Use the atomic version instead when your search 
//includes such files (the atomic version will also fail invalid files, but much faster).
$pattern = '/<html>.*?<head>.*?<title>.*?<\/title>.*?<\/head>.*?<body[^>]*>.*?<\/body>.*?<\/html>/';

//HTML file (atomic)
//Matches a complete HTML file.
//Atomic grouping maintains the regular expression's performance on invalid HTML files.
$pattern = '<html>(?>.*?<head>)(?>.*?<title>)(?>.*?<\/title>)(?>.*?<\/head>)(?>.*?<body[^>]*>)(?>.*?<\/body>).*?<\/html>';

//HTML tag
//Matches the opening and closing pair of whichever HTML tag comes next.
//The name of the tag is stored into the first capturing group.
//The text between the tags is stored into the second capturing group.
$pattern = '<([A-Z][A-Z0-9]*)[^>]*>(.*?)</\1>';

//HTML tag
//Matches the opening and closing pair of a specific HTML tag.
//Anything between the tags is stored into the first capturing group.
//Does NOT properly match tags nested inside themselves.
$pattern = '<%TAG%[^>]*>(.*?)</%TAG%>';

//HTML tag
//Matches any opening or closing HTML tag, without its contents.
$pattern = '</?[a-z][a-z0-9]*[^<>]*>';

// script di controllo
$txt = "<!-- questo è un commento -->";
$pattern = '/<!--.*?-->/';
if (preg_match($pattern, $txt)) {
    echo "esiste.";
} else {
    echo "non esiste.";
}