Espressioni regolari in un'applicazione Objective-C Cocoa


173

Il googling iniziale indica che non esiste un modo integrato per eseguire espressioni regolari in un'applicazione Cocoa Objective-C.

Quindi quattro domande:

  1. È davvero vero?

  2. Ma stai scherzando?

  3. Ok, allora c'è una bella libreria open source che mi consigliate?

  4. Quali sono i modi per avvicinarsi abbastanza senza importare una libreria, forse con la classe NSScanner?


4
Hmmmm ... Mi chiedo cosa succede se usi Monotouch. +1 per la domanda.
Dan Rosenstark,

Risposte:



42
  1. Sì, non c'è supporto regex in Cocoa. Se sei interessato solo alla corrispondenza booleana, puoi utilizzare NSPredicate che supporta la sintassi della regex dell'ICU. Ma di solito sei interessato alla posizione della corrispondenza o alla posizione delle sottoespressioni e non puoi ottenerla con NSPredicate.
  2. Come accennato, è possibile utilizzare le funzioni POSIX di regex . Ma sono considerati lenti e la sintassi della regex è limitata rispetto ad altre soluzioni (ICU / pcre ).
  3. Esistono molte librerie OSS, CocoaDev ha un ampio elenco .
  4. Ad esempio, RegExKitLite non richiede alcuna libreria, è sufficiente aggiungere .m e .h al progetto.

    (La mia lamentela nei confronti di RegExKitLite è che estende NSString tramite la categoria, ma può anche essere considerata una funzionalità. Inoltre, utilizza le librerie ICU non pubbliche fornite con il sistema operativo, che non è raccomandato da Apple.)


3
Tieni presente che le funzioni regex POSIX non funzionano con Unicode (solo ASCII).
Tom Dalling,

Cordiali saluti, l'URL di NSPredicate è un collegamento interrotto
taber

11
iOS supporta espressioni regolari per ricerche di sottostringa, ad es[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor,

1
Disponibile anche in Lion (10.7) # se MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_3_2 <= __IPHONE_OS_VERSION_MAX_ALLOWED
Maciej Swic,

Trovo corretto utilizzare librerie ICU non pubbliche, perché se è necessario utilizzarlo, è perché non esiste un supporto regex incorporato nella versione di Cocoa. Se usi quelle librerie, significa anche che stai costruendo per sistemi più vecchi, che non verranno più modificati in quanto non supportati. Se stai costruendo per vecchio e nuovo, usi RegExKitLite come fallback se NSRegularExpression non esiste. (Sì, ci sono ancora persone che lavorano su sistemi più vecchi).


12

È possibile utilizzare la libreria di espressioni regolari POSIX (Sì per un sistema operativo compatibile POSIX). Provare

man 3 regex

Oh, capisco. questo è un modo per farlo in C dritto, che dovrebbe presumibilmente funzionare in qualsiasi app C-obiettivo. Figo, grazie! è sostanzialmente il modo accettato per farlo?
Dreeves,

È un modo, che non richiede dipendenze aggiuntive. Esistono altre opzioni, in termini di librerie open source che è possibile importare (PCRE, per regex Perl, la libreria Boost RegEx se si utilizza Obj-C ++ o altre elencate in altre risposte).
Adam Wright,

Svantaggi nel mescolare la C diritta con Objective-C? Potresti forse includere uno snippet di codice per la conversione da e verso NSString? grazie ancora!
Dreeves,

Objective-C è costruito sopra C, quindi non stai davvero mescolando nulla. La maggior parte delle persone utilizza una libreria, poiché offre un'API più semplice da utilizzare.
Marc Charbonneau,

5
E poiché le funzioni regex POSIX funzionano solo con stringhe ASCII.
Tom Dalling,

8

La soluzione di hacking economica e sporca che utilizzo per risolvere i problemi di analisi REGEX e JSON è quella di creare un oggetto UIWebView e iniettare le funzioni Javascript per eseguire l'analisi. La funzione javascript quindi restituisce una stringa del valore (o elenco di valori) a cui tengo. In effetti, è possibile archiviare un piccolo set di librerie di funzioni personalizzate per attività particolari e quindi semplicemente chiamarle secondo necessità.

Non so se questa tecnica si ridimensiona a enormi volumi di richieste di analisi ripetute, ma per operazioni transazionali veloci fa il lavoro senza dipendere da risorse o codici esterni extra che potresti non capire.


7

Mi piace il framework AGRegex che utilizza PCRE, utile se si è abituati alla sintassi PCRE. La migliore versione di questo framework è quella nel client Colloquy IRC poiché è stata aggiornata per usare PCRE 6.7:

http://colloquy.info/project/browser/trunk/Frameworks/AGRegex

È molto leggero, molto più di RegExKit (anche se ovviamente non altrettanto capace).


Perché meno capace se ha regex pienamente compatibile con perl?
Dreeves,

I metodi helper Objective-C associati non sono così estesi come quelli in RegExKit, tuttavia vanno bene per la maggior parte degli scopi.
Rob Keniger


5

Durante la mia ricerca su questo argomento mi sono imbattuto in CocoaOniguruma che utilizza Oniguruma , il motore di espressioni regolari dietro Ruby1.9 e PHP5. Sembra un po 'più recente rispetto all'attuale OregKit (in giapponese). Non sono sicuro di come si sovrappongano ad altri attacchi.


4

Cercando su Google, ho trovato questa libreria: RegexOnNSString

Libreria open source, contenente funzioni come:

-(NSString *) stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement caseInsensitive:(BOOL)ignoreCase

e usando la NSRegularExpressionclasse. Abbastanza facile da usare e non devi preoccuparti di nulla.

Si noti che NSRegularExpressionè disponibile da Mac OS X v10.7 e IOS 4.0, come indicato da Datasmid.


1

Lo rendo facile. Aggiungo un nuovo file C ++ al mio progetto Objective C, lo rinomino come .mm e quindi creo una classe C ++ standard all'interno. Quindi, creo un metodo di classe statica nella sezione "public:" per una funzione C ++ che accetta un NSString e restituisce un NSString (o NSArray, se è quello che vuoi). Quindi converto NSString in C ++ std :: string in questo modo:

// If anyone knows a more efficient way, let me know in the comments.
// The "if" condition below is because ObjC crashes if converting to
// std::string if the string is nil or empty.
// assume #include <string>
std::string s = "";
if (([sInput != nil]) && (!([sInput isEqualTo:@""]))) {
  std::string sTemp([sInput UTF8String]);
  s = sTemp;
}

Da lì, posso usare regex_replace in questo modo:

// assume #include <regex>
std::string sResult = std::regex_replace(sSource,sRegExp,sReplaceWith);

Quindi, posso riconvertire quella stringa std :: string in una NSString con:

NSString *sResponse2 = @(sResult.c_str());

Se stai usando questo C ++ solo per questa funzione, potresti trovare adatto chiamare questo file extra.mm (nome classe Extra) e inserire questo metodo di classe statica, quindi aggiungere altri metodi di classe statica quando arriva la situazione dove ha senso farlo in C ++ perché in alcuni casi è meno problematico. (Ci sono casi in cui ObjC fa qualcosa con meno righe di codice e alcuni casi in cui C ++ lo fa con meno righe di codice.)

PS Ancora un altro modo con questo è usare un file .mm ma creare un wrapper Objective C attorno all'uso di std :: string e std :: regex_replace () (o regex_match ()).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.