[This article is available also in ENGLISH: Regular Expressions in Objective-C with the NSRegularExpression class]
Nel post di oggi vediamo come utilizzare le espressioni regolari in Objective-C. Per farlo, creiamo una semplice applicazione che legge un file di testo e cerca al suo interno tutte le occorrenze di un determinato pattern. Supponiamo ad esempio di avere un file contenente degli ordini in cui sono presenti, per ciascun ordine, una riga contenente l’identificativo e le righe di dettaglio dell’ordine in cui compaiono gli oggetti appartenenti all’ordine, le quantità ed i prezzi. Tutti gli ordini sono elencati in sequenza e quello che vogliamo fare è estrapolare le sole righe contenenti gli identificativi degli ordini.
Un esempio del nostro file di input potrebbe essere il seguente:
OrderID:12345 Item1;3;10.43 Item2;1;7.20 Item3;1;8.99 OrderID:34567 Item1;1;4.50 Item2;2;9.99 OrderID:22873 Item1;1;10.0 OrderID:39087 Item1;2;19.90
e quello che vogliamo ottenere è l’elenco delle sole righe contenenti gli ID degli ordini. L’output del nostro programma dovrà quindi essere:
OrderID:12345 OrderID:34567 OrderID:22873 OrderID:39087
Iniziamo con il definire il pattern che ci permette di identificare le sequenze che ci interessano. Le righe che dobbiamo ritornare contengono sempre la stringa “OrderID:” seguita da un codice numerico che rappresenta l’ID dell’ordine. Possiamo quindi definire la regular expression che fa al caso nostro in questo modo: OrderID:\d+
Salviamo l’elenco di ordini di esempio su un file di testo e chiamiamolo “orders.txt”. A questo punto siamo pronti per procedere. Creiamo in XCode un nuovo progetto OS X di tipo “Command Line Tool”, lo chiamiamo TestRegex e selezioniamo come tipologia “Foundation”. Le due immagini seguenti mostrano queste operazioni:
Una volta creato il progetto, quello che dobbiamo editare è il file principale dell’applicazione, chiamato main.m.
Lo scopo del nostro programma, come detto, è quello di leggere un file di testo ed estrarre, tramite l’utilizzo di espressioni regolari, le stringhe che ci interessano.
Quindi iniziamo con il definire il path in cui si trova il nostro file contenente i dati e ad estrarre il suo contenuto, inserendolo in un oggetto stringa:
NSString *fileNameString = @"/Users/Dede/Documents/orders.txt"; NSString *stringFromFile = [[NSString alloc] initWithContentsOfFile:fileNameString encoding:NSASCIIStringEncoding error:&error];
Ora dobbiamo definire la nostra regex, ovvero la struttura del pattern che vogliamo ricercare e che abbiamo già analizzato ed individuato in precedenza. La classe da utilizzare per questo scopo è NSRegularExpression che può essere instanziata con il metodo initWithPattern a cui viene passato il pattern della regex.
NSRegularExpression* regex = [[NSRegularExpression alloc] initWithPattern:@"OrderID:\\d+" options:0 error:nil];
Il campo options può assumere diversi valori previsti dall’enumerare
NSRegularExpressionOptions e dopo vedremo un esempio. Per ora lasciamo il valore 0 e cioè le impostazioni di default.
Per prima cosa possiamo vedere come fare per ritornare il numero di occorrenze che matchano con il pattern della nostra regex. Per farlo invochiamo sul nostro oggetto NSRegularExpression il metodo numberOfMatchesInString a cui passiamo la stringa in cui cercare, le opzioni di ricerca ed il range in cui effettuare la ricerca all’interno della stringa.
long n = [regex numberOfMatchesInString:stringFromFile options:0 range:NSMakeRange(0, [stringFromFile length])];
Nel nostro caso abbiamo indicato come stringa oggetto della ricerca il contenuto del file che abbiamo precedentemente estratto nella stringa “stringFromFile” e come range di ricerca tutta la sua lunghezza(da 0 alla lunghezza della stringa).
Se il numero di occorrenze trovate è maggiore di 0 e quindi ne è stata trovata almeno una, recuperiamo la lista di occorrenze che matchano con la nostra regex. Per farlo utilizziamo questa volta il metodo matchesInString che ci ritorna un array di oggetti NSTextCheckingResult che possiamo scorrere ed andare ad estrarre, per ciascuno elemento, l’intera stringa matchata tramite la property range.
Di seguito riporto il programma completo:
// // main.m // TestRegex // // Created by Davis Molinari on 19/11/14. // Copyright (c) 2014 Davis Molinari. All rights reserved. // #importint main(int argc, const char * argv[]) { @autoreleasepool { NSError *error; NSString *fileNameString = @"/Users/Dede/Documents/orders.txt"; NSString *stringFromFile = [[NSString alloc] initWithContentsOfFile:fileNameString encoding:NSASCIIStringEncoding error:&error]; NSRegularExpression* regex = [[NSRegularExpression alloc] initWithPattern:@"OrderID:\\d+" options:0 error:nil]; long n = [regex numberOfMatchesInString:stringFromFile options:0 range:NSMakeRange(0, [stringFromFile length])]; NSLog(@"Number of match: %ld", n); if (n > 0) { NSArray *matches = [regex matchesInString:stringFromFile options:0 range:NSMakeRange(0, [stringFromFile length])]; for (NSTextCheckingResult *match in matches) { NSString* matchText = [stringFromFile substringWithRange:[match range]]; NSLog(@"Found String: %@\n", matchText); } } else NSLog(@"Nessuna occorrenza trovata nel file %@", fileNameString); } return 0; }
Proviamo ad eseguire il programma, cliccando sul pulsante “Build and Run” di Xcode, e vediamo se il risultato è quello che ci aspettiamo.
L’output generato è il seguente:
Come vediamo sono state identificate le 4 occorrenze del pattern “OrderID:” seguito dal codice dell’ordine, che avevamo identificato come risultato atteso.
Il progetto Xcode completo dell’esempio può essere scaricato qui:
Pingback: Regular Expressions in Objective-C with the NSRegularExpression class | Dede Blog