Espressioni regolari in Objective-C con la classe NSRegularExpression

[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:

Regex Output

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.
//

#import <Foundation/Foundation.h>

int 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:
Regex Program Output
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:

One thought on “Espressioni regolari in Objective-C con la classe NSRegularExpression

  1. Pingback: Regular Expressions in Objective-C with the NSRegularExpression class | Dede Blog

Leave a Reply

Your email address will not be published. Required fields are marked *