TOC

This article is currently in the process of being translated into Italian (~99% done).

Regular Expressions (Regex):

Regex Modifiers

Negli articoli precedenti abbiamo parlato di cosa sono le Regular Expressions e di come utilizzarle in C# per le corrispondenze, le sostituzioni e così via. A questo punto, dovreste già aver capito quanto siano potenti le Regular Expressions e come possano aiutarvi in molte situazioni, ma diventano ancora più potenti quando conoscete i possibili modificatori.

Quando si lavora con le Regular Expressions, è possibile utilizzare uno o più modificatori per controllare il comportamento del motore di ricerca. Ad esempio, un processo di ricerca Regex è solitamente sensibile alle maiuscole e alle minuscole, il che significa che "a" non è la stessa cosa di "A". Tuttavia, in molte situazioni, si desidera che la corrispondenza sia insensibile alle maiuscole e alle minuscole, in modo che il carattere "a" sia solo una lettera, non importa se minuscola o maiuscola. Basta fornire l'opzione RegexOptions.IgnoreCase quando si crea l'istanza di Regex e la corrispondenza sarà insensibile alle maiuscole e alle minuscole.

Tutti i modificatori disponibili si trovano nell'enumerazione RegexOptions. Alcuni di essi sono comuni a tutti i linguaggi di programmazione che supportano lo standard delle espressioni regolari, mentre altri sono specifici del framework .NET.

Come si vedrà nel primo esempio, i modificatori Regex sono solitamente specificati come secondo parametro quando si crea l'istanza Regex. È possibile specificare più di un'opzione separandole con un carattere pipe (|), come in questo caso:

new Regex("[a-z]+", RegexOptions.IgnoreCase | RegexOptions.Singleline);

Esaminiamo ora tutti i modificatori per darvi un'idea di come funzionano e di cosa possono fare per voi.

RegexOptions.IgnoreCase

Questo sarà probabilmente uno dei modificatori più utilizzati. Come descritto in precedenza, cambia le Regular Expressions da sensibili alla distinzione tra maiuscole e minuscole a insensibili a queste ultime. Questo fa una grande differenza, come si può vedere in questo esempio:

public void IgnoreCaseModifier()
{
	string testString = "Hello World";
	string regexString = @"^[a-z\s]+$";
	Regex caseSensitiveRegex = new Regex(regexString);
	Regex caseInsensitiveRegex = new Regex(regexString, RegexOptions.IgnoreCase);

	Console.WriteLine("Case-sensitive match: " + caseSensitiveRegex.IsMatch(testString));
	Console.WriteLine("Case-insensitive match: " + caseInsensitiveRegex.IsMatch(testString));
}

Specifichiamo una Regex semplice, progettata per corrispondere solo alle lettere (a-z) e agli spazi bianchi. Lo usiamo per creare due istanze di Regex: Una senza il modificatore RegexOptions.IgnoreCase e una con esso, e poi proviamo a far corrispondere la stessa stringa di prova, che consiste in caratteri minuscoli e MAIUSCOLI e un singolo spazio. Il risultato, probabilmente non sorprendente, sarà questo:

Case-sensitive match: False
Case-insensitive match: True

RegexOptions.Singleline

Nelle Regular Expressions, il punto (.) è fondamentalmente un carattere di richiamo. Tuttavia, per impostazione predefinita, non corrisponde alle interruzioni di riga, il che significa che è possibile utilizzare il punto per corrispondere a un'intera riga di lettere, numeri, caratteri speciali e così via, ma la corrispondenza terminerà non appena si incontra un'interruzione di riga. Tuttavia, se si fornisce il modificatore Singleline, il punto corrisponderà anche alle interruzioni di riga. Permettetemi di dimostrare la differenza:

public void SinglelineModifier()
{
	string testString = 
						@"Hello World
						This string contains
						several lines";
	string regexString = ".*";
	
	Regex normalRegex = new Regex(regexString);
	Regex singlelineRegex = new Regex(regexString, RegexOptions.Singleline);			

	Console.WriteLine("Normal regex: " + normalRegex.Match(testString).Value);
	Console.WriteLine("Singleline regex: " + singlelineRegex.Match(testString).Value);
}

Il risultato sarà simile a questo:

Normal regex: Hello World

Singleline regex: Hello World
							This string contains
                            several lines

RegexOptions.Multiline

Come abbiamo detto in questo capitolo, le Regular Expressions sono composte da molti caratteri diversi che hanno uno scopo speciale. Un altro esempio sono questi due caratteri: ^ e $. Li abbiamo usati nell'esempio della sensibilità alle maiuscole e minuscole, per far corrispondere l'inizio e la fine di una stringa. Tuttavia, fornendo il modificatore Multiline, è possibile cambiare questo comportamento, passando dalla corrispondenza con l'inizio e la fine di una stringa alla corrispondenza con l'inizio e la fine delle righe. Ciò è molto utile quando si desidera trattare singolarmente le righe corrispondenti. Ecco un esempio:

public void MultilineModifier()
{
	string testString =
						@"Hello World
						This string contains
						several lines";
	string regexString = "^.*$";

	Regex singlelineRegex = new Regex(regexString, RegexOptions.Singleline);
	Regex multilineRegex = new Regex(regexString, RegexOptions.Multiline);

	Console.WriteLine("Singleline regex: " + singlelineRegex.Match(testString).Value);

	Console.WriteLine("Multiline regex:");
	MatchCollection matches = multilineRegex.Matches(testString);
	for(int i = 0; i < matches.Count; i++)
		Console.WriteLine("Line " + i + ": " + matches[i].Value.Trim());
}

Si noti come utilizzo una stringa di test composta da più righe e poi utilizzo i meccanismi di corrispondenza in modo diverso: Con singlelineRegex, trattiamo l'intera stringa di test come un'unica riga, anche se contiene interruzioni di riga, come abbiamo detto sopra. Quando si usa il multilineRegex, si tratta la stringa di test come più righe, ognuna delle quali risulta in una corrispondenza. Possiamo usare il metodo Regex.Matches() per catturare ogni riga e lavorarci; in questo caso, ci limitiamo a inviarla alla console.

RegexOptions.Compiled

Sebbene le Regular Expressions siano generalmente abbastanza veloci, possono rallentare un po' le cose se sono molto complesse e se vengono eseguite molte volte, ad esempio in un ciclo. In queste situazioni, si può usare il modificatore RegexOptions.Compiled, che consente al framework di compilare la Regex in un assembly. Questo costa un po' di tempo in più al momento della creazione, rispetto alla semplice istanziazione di un oggetto Regex, ma renderà più veloci tutte le operazioni Regex successive (ricerche, ecc.):

Regex compiledRegex = new Regex("[a-z]*", RegexOptions.Compiled);

Altri modificatori

I modificatori di cui sopra sono i più interessanti, ma ce ne sono altri, che esamineremo un po' più velocemente:

  • RegexOptions.CultureInvariant: Con questo modificatore, le differenze culturali nella lingua vengono ignorate. Questo è importante soprattutto se l'applicazione lavora con più lingue diverse dall'inglese.
  • RegexOptions.ECMAScript: Cambia la variante di Regex utilizzata dalla versione specifica di .NET allo standard ECMAScript. Questo dovrebbe essere raramente necessario.
  • RegexOptions.ExplicitCapture: Normalmente, un insieme di parentesi in una Regex agisce come un gruppo di cattura, consentendo di accedere a ciascun valore catturato tramite un indice. Se si specifica il modificatore ExplicitCapture, questo comportamento viene modificato in modo che solo i gruppi denominati vengano catturati e memorizzati per un successivo recupero.
  • RegexOptions.IgnorePatternWhitespace: Quando questo modificatore è abilitato, gli spazi bianchi nella Regex vengono ignorati e si possono persino includere commenti, preceduti dal carattere hash (#).
  • RegexOptions.RightToLeft: cambia la corrispondenza in modo che parta da destra e si sposti a sinistra, invece che da sinistra a destra come di default.

Riepilogo

Come si può vedere, ci sono molti importanti modificatori Regex che è bene conoscere per sfruttare al meglio le Regular Expressions e per supportare il maggior numero possibile di casistiche di utilizzo.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!