Expressions régulières dans une application Objective-C Cocoa

173

La recherche initiale sur Google indique qu'il n'existe aucun moyen intégré de créer des expressions régulières dans une application Objective-C Cocoa.

Donc quatre questions:

  1. Est-ce vraiment vrai?

  2. Vous plaisantez j'espère?

  3. Ok, alors y a-t-il une belle bibliothèque open-source que vous recommandez?

  4. Quels sont les moyens de se rapprocher suffisamment sans importer de bibliothèque, peut-être avec la classe NSScanner?

dreeves
la source
4
Hmmmm ... Je me demande ce qui se passe si vous utilisez Monotouch. +1 pour la question.
Dan Rosenstark

Réponses:

141

J'ai remarqué qu'à partir d'iOS 4.0, Apple fournit une classe NSRegularExpression . De plus, à partir de 10.7, la classe est disponible sous OS X .

Philip Jespersen
la source
11
aussi Mac OS X 10.7 maintenant
user102008
42
  1. Oui, il n'y a pas de support regex dans Cocoa. Si vous n'êtes intéressé que par la correspondance booléenne, vous pouvez utiliser NSPredicate qui prend en charge la syntaxe d'expression régulière ICU. Mais généralement, vous êtes intéressé par la position de la correspondance ou la position des sous-expressions, et vous ne pouvez pas l'obtenir avec NSPredicate.
  2. Comme mentionné, vous pouvez utiliser les fonctions regex POSIX . Mais ils sont considérés comme lents, et la syntaxe des regex est limitée par rapport aux autres solutions (ICU / pcre ).
  3. Il existe de nombreuses bibliothèques OSS, CocoaDev en a une longue liste .
  4. RegExKitLite par exemple ne nécessite aucune bibliothèque, ajoutez simplement le .m et .h à votre projet.

    (Ma plainte contre RegExKitLite est qu'il étend NSString via la catégorie, mais il peut également être considéré comme une fonctionnalité. Il utilise également les bibliothèques ICU non publiques fournies avec le système d'exploitation, ce qui n'est pas recommandé par Apple.)

mfazekas
la source
3
Gardez à l'esprit que les fonctions regex POSIX ne fonctionnent pas avec unicode (ASCII uniquement).
Tom Dalling
FYI que NSPredicate url est un lien cassé
taber
11
iOS prend en charge les expressions régulières pour les recherches de sous-chaînes, par exemple[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor
1
Également disponible dans Lion (10.7) #if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_3_2 <= __IPHONE_OS_VERSION_MAX_ALLOWED
Maciej Swic
Je trouve bien d'utiliser des bibliothèques ICU non publiques, car si vous avez besoin de les utiliser, c'est parce qu'il n'y a pas de support regex intégré dans votre version de Cocoa. Si vous utilisez ces bibliothèques, cela signifie également que vous construisez pour des systèmes plus anciens, qui ne seront plus modifiés car ils ne sont pas pris en charge. Si vous créez à la fois pour l'ancien et le nouveau, vous utilisez le RegExKitLite comme solution de secours si NSRegularExpression n'existe pas. (Oui, il y a encore des gens qui travaillent sur des systèmes plus anciens).
19

RegexKit est le meilleur que j'ai trouvé à ce jour. Très cacao: y. J'utilise la version "Lite" dans plusieurs de nos applications iPhone:

sourceforge

lingonikorg

avocat
la source
1
Je seconde RegexKit Lite. Très agréable!
Dave Dribin
1
Cool, plus il y a de gens qui l'utilisent, mieux ça va probablement devenir!
avocade
12

Vous pouvez utiliser la bibliothèque d'expressions régulières POSIX (Yay pour un système d'exploitation compatible POSIX). Essayer

man 3 regex
Adam Wright
la source
Oh je vois. c'est une façon de le faire en C droit, qui devrait vraisemblablement fonctionner dans n'importe quelle application objective-C. cool merci! est-ce fondamentalement la manière acceptée de procéder?
dreeves
C'est un moyen qui ne nécessite aucune dépendance supplémentaire. Il y a d'autres choix, en termes de bibliothèques open source que vous pouvez importer (PCRE, pour les expressions régulières Perl, la bibliothèque Boost RegEx si vous utilisez Obj-C ++, ou d'autres listées dans d'autres réponses).
Adam Wright
Y a-t-il des inconvénients à mélanger directement C avec Objective-C? Pourriez-vous peut-être inclure un extrait de code pour la conversion vers et depuis NSString? Merci encore!
dreeves
Objective-C est construit sur C, donc vous ne mélangez vraiment rien. La plupart des gens utilisent cependant une bibliothèque, car elle offre une API plus facile à utiliser.
Marc Charbonneau
5
Et parce que les fonctions d'expression régulière POSIX ne fonctionnent qu'avec des chaînes ASCII.
Tom Dalling
8

La solution de piratage bon marché et sale que j'utilise pour résoudre les problèmes d'analyse REGEX et JSON consiste à créer un objet UIWebView et à injecter des fonctions Javascript pour effectuer l'analyse. La fonction javascript renvoie ensuite une chaîne de la valeur (ou liste de valeurs) qui me tient à cœur. En fait, vous pouvez stocker une petite bibliothèque de fonctions personnalisées pour des tâches particulières, puis les appeler selon vos besoins.

Je ne sais pas si cette technique s'adapte à d'énormes volumes de demandes d'analyse répétées, mais pour les transactions rapides, elle fait le travail sans dépendre de ressources externes supplémentaires ou de code que vous ne comprenez peut-être pas.

Mark Caufman
la source
7

J'aime le framework AGRegex qui utilise PCRE, pratique si vous êtes habitué à la syntaxe PCRE. La meilleure version de ce framework est celle du client Colloquy IRC car il a été mis à niveau pour utiliser PCRE 6.7:

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

Il est très léger, bien plus que RegExKit (bien que pas aussi capable bien sûr).

Rob Keniger
la source
Pourquoi moins capable s'il a une regex entièrement compatible avec Perl?
dreeves
Les méthodes d'assistance Objective-C associées ne sont pas aussi étendues que celles de RegExKit, mais elles conviennent à la plupart des cas.
Rob Keniger
6

NSRegularExpression est disponible depuis Mac OS X v10.7 et IOS 4.0.

bbaassssiiee
la source
5

Au cours de ma recherche sur ce sujet, je suis tombé sur CocoaOniguruma qui utilise Oniguruma , le moteur d'expression régulière derrière Ruby1.9 et PHP5. Il semble un peu plus récent par rapport à l' OregKit existant (en japonais). Je ne sais pas comment ceux-ci se comparent aux autres liaisons.

newtonapple
la source
4

Googler un peu, j'ai trouvé cette bibliothèque: RegexOnNSString

Bibliothèque open source, contenant des fonctions telles que:

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

et en utilisant la NSRegularExpressionclasse. Très facile à utiliser et pas besoin de s'inquiéter de quoi que ce soit.

Veuillez noter que NSRegularExpressionc'est disponible depuis Mac OS X v10.7 et IOS 4.0, comme l'a mentionné Datasmid.

Nickeyzzz
la source
1

Je vous facilite la tâche. J'ajoute un nouveau fichier C ++ à mon projet Objective C, le renomme en .mm, puis crée une classe C ++ standard à l'intérieur. Ensuite, je crée une méthode de classe statique dans la section "public:" pour une fonction C ++ qui prend une NSString et renvoie une NSString (ou NSArray, si c'est ce que vous voulez). Je convertis ensuite NSString en C ++ std :: string comme ceci:

// 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;
}

À partir de là, je peux utiliser regex_replace comme ceci:

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

Ensuite, je peux reconvertir cette std :: string en une NSString avec:

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

Si vous n'utilisez ce C ++ que pour cette fonction, vous trouverez peut-être approprié d'appeler ce fichier extra.mm (nom de classe Extra) et de placer cette méthode de classe statique, puis d'ajouter d'autres méthodes de classe statique lorsque la situation se présente où il est logique de le faire en C ++ car c'est moins compliqué dans certains cas. (Il y a des cas où ObjC fait quelque chose avec moins de lignes de code, et certains cas où C ++ le fait avec moins de lignes de code.)

PS Encore une autre façon avec ceci est d'utiliser un fichier .mm mais de créer un wrapper Objective C autour de l'utilisation de std :: string et std :: regex_replace () (ou regex_match ()).

Volomike
la source