Reguläre Ausdrücke in einer Objective-C Cocoa-Anwendung

173

Das anfängliche Googeln zeigt an, dass es in einer Objective-C Cocoa-Anwendung keine integrierte Möglichkeit gibt, reguläre Ausdrücke auszuführen.

Also vier Fragen:

  1. Stimmt das wirklich?

  2. Willst du mich verarschen?

  3. Ok, gibt es dann eine nette Open-Source-Bibliothek, die Sie empfehlen?

  4. Was sind Möglichkeiten, nahe genug zu kommen, ohne eine Bibliothek zu importieren, vielleicht mit der NSScanner-Klasse?

träumt
quelle
4
Hmmmm ... Ich frage mich, was passiert, wenn Sie Monotouch verwenden. +1 für die Frage.
Dan Rosenstark

Antworten:

42
  1. Ja, es gibt keine Regex-Unterstützung in Cocoa. Wenn Sie nur an booleschen Übereinstimmungen interessiert sind, können Sie NSPredicate verwenden, das die ICU-Regex-Syntax unterstützt. Normalerweise interessieren Sie sich jedoch für die Position der Übereinstimmung oder die Position von Unterausdrücken, und Sie können sie mit NSPredicate nicht erhalten.
  2. Wie bereits erwähnt, können Sie Regex-POSIX-Funktionen verwenden . Sie gelten jedoch als langsam und die Regex-Syntax ist im Vergleich zu anderen Lösungen (ICU / pcre ) begrenzt.
  3. Es gibt viele OSS-Bibliotheken, CocoaDev hat eine umfangreiche Liste .
  4. Für RegExKitLite sind beispielsweise keine Bibliotheken erforderlich. Fügen Sie einfach die Dateien .m und .h zu Ihrem Projekt hinzu.

    (Meine Beschwerde gegen RegExKitLite ist, dass es NSString über die Kategorie erweitert, aber es kann auch als Funktion betrachtet werden. Außerdem werden die nicht öffentlichen ICU-Bibliotheken verwendet, die mit dem Betriebssystem geliefert werden, was von Apple nicht empfohlen wird.)

mfazekas
quelle
3
Beachten Sie, dass POSIX-Regex-Funktionen nicht mit Unicode funktionieren (nur ASCII).
Tom Dalling
Zu Ihrer Information, dass NSPredicate URL ein defekter Link ist
Taber
11
iOS unterstützt reguläre Ausdrücke für die Suche nach Teilzeichenfolgen, z. B.[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor
1
Auch verfügbar in 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
Ich finde es in Ordnung, nicht öffentliche ICU-Bibliotheken zu verwenden, denn wenn Sie sie verwenden müssen, liegt es daran, dass Ihre Version von Cocoa keine integrierte Regex-Unterstützung enthält. Wenn Sie diese Bibliotheken verwenden, bedeutet dies auch, dass Sie für ältere Systeme erstellen, die nicht mehr geändert werden, da sie nicht unterstützt werden. Wenn Sie sowohl für alte als auch für neue Gebäude erstellen, verwenden Sie RegExKitLite als Fallback, wenn NSRegularExpression nicht vorhanden ist. (Ja, es gibt immer noch Leute, die an älteren Systemen arbeiten).
19

RegexKit ist das beste, das ich bisher gefunden habe. Sehr Kakao: y. Ich verwende die "Lite" -Version in mehreren unserer iPhone-Apps:

Quellschmiede

lingonikorg

Avocade
quelle
1
Ich zweite RegexKit Lite. Sehr schön!
Dave Dribin
1
Cool, je mehr Leute es benutzen, desto besser wird es wahrscheinlich!
Avocade
12

Sie können die POSIX Regular Expressions-Bibliothek verwenden (Yay für ein POSIX-kompatibles Betriebssystem). Versuchen

man 3 regex
Adam Wright
quelle
Oh, ich verstehe. Dies ist eine Möglichkeit, dies in Straight C zu tun, was vermutlich in jeder Objective-C-App funktionieren sollte. Cool, danke! Ist das im Grunde der akzeptierte Weg, dies zu tun?
Dreeves
Es ist ein Weg, der keine zusätzlichen Abhängigkeiten erfordert. Es gibt andere Möglichkeiten in Bezug auf Open Source-Bibliotheken, die Sie importieren können (PCRE für Perl-Regexes, The Boost RegEx-Bibliothek, wenn Sie Obj-C ++ verwenden, oder andere, die in anderen Antworten aufgeführt sind).
Adam Wright
Irgendwelche Nachteile beim Mischen von reinem C mit Objective-C? Könnten Sie vielleicht ein Code-Snippet für die Konvertierung von und nach NSString einfügen? Danke noch einmal!
Dreeves
Objective-C baut auf C auf, sodass Sie nichts wirklich mischen. Die meisten Leute benutzen jedoch eine Bibliothek, da sie eine API bietet, die einfacher zu benutzen ist.
Marc Charbonneau
5
Und weil POSIX-Regex-Funktionen nur mit ASCII-Zeichenfolgen funktionieren.
Tom Dalling
8

Die billige und schmutzige Hack-Lösung, mit der ich REGEX- und JSON-Parsing-Probleme löse, besteht darin, ein UIWebView-Objekt zu erstellen und Javascript-Funktionen einzufügen, um das Parsing durchzuführen. Die Javascript-Funktion gibt dann eine Zeichenfolge des Werts (oder der Werteliste) zurück, der mir wichtig ist. Tatsächlich können Sie eine kleine Bibliothek mit Funktionen speichern, die für bestimmte Aufgaben angepasst sind, und diese dann nach Bedarf aufrufen.

Ich weiß nicht, ob diese Technik auf große Mengen wiederholter Parsing-Anforderungen skaliert werden kann, aber für schnelle Transaktionsaufgaben wird die Aufgabe erledigt, ohne von zusätzlichen externen Ressourcen oder Code abhängig zu sein, die Sie möglicherweise nicht verstehen.

Mark Caufman
quelle
7

Ich mag das AGRegex-Framework, das PCRE verwendet, praktisch, wenn Sie an die PCRE-Syntax gewöhnt sind. Die beste Version dieses Frameworks ist die im Colloquy IRC-Client, da es auf PCRE 6.7 aktualisiert wurde:

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

Es ist sehr leicht, viel mehr als RegExKit (obwohl es natürlich nicht so fähig ist).

Rob Keniger
quelle
Warum weniger fähig, wenn es voll perl-kompatiblen regulären Ausdruck hat?
Dreeves
Die zugehörigen Objective-C-Hilfsmethoden sind bei weitem nicht so umfangreich wie die in RegExKit, sind jedoch für die meisten Zwecke in Ordnung.
Rob Keniger
6

NSRegularExpression ist seit Mac OS X 10.7 und IOS 4.0 verfügbar.

bbaassssiiee
quelle
5

Bei meiner Suche zu diesem Thema bin ich auf CocoaOniguruma gestoßen , das Oniguruma verwendet , die Engine für reguläre Ausdrücke hinter Ruby1.9 und PHP5. Es scheint etwas neuer im Vergleich zum vorhandenen OregKit (auf Japanisch). Nicht sicher, wie sich diese gegen andere Bindungen stapeln.

Newtonapple
quelle
4

Googeln ein wenig, fand diese Bibliothek: RegexOnNSString

Open Source Bibliothek mit Funktionen wie:

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

und mit NSRegularExpressionKlasse. Ganz einfach zu bedienen und Sie müssen sich um nichts kümmern.

Bitte beachten Sie, dass dies NSRegularExpressionseit Mac OS X 10.7 und IOS 4.0 verfügbar ist, wie von Datasmid erwähnt.

nickeyzzz
quelle
1

Ich mache es einfach. Ich füge meinem Objective C-Projekt eine neue C ++ - Datei hinzu, benenne sie in .mm um und erstelle dann eine Standard-C ++ - Klasse darin. Dann erstelle ich im Abschnitt "public:" eine statische Klassenmethode für eine C ++ - Funktion, die einen NSString verwendet und einen NSString zurückgibt (oder NSArray, wenn Sie dies wünschen). Ich konvertiere dann NSString in C ++ std :: string wie folgt:

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

Von dort aus kann ich regex_replace wie folgt verwenden:

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

Dann kann ich diesen std :: string wieder in einen NSString konvertieren mit:

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

Wenn Sie dieses C ++ nur für diese Funktion verwenden, ist es möglicherweise geeignet, diese Datei extra.mm (Klassenname Extra) aufzurufen, diese statische Klassenmethode einzufügen und dann andere statische Klassenmethoden hinzuzufügen, wenn die Situation eintrifft wo es nur Sinn macht, es in C ++ zu tun, weil es in einigen Fällen weniger mühsam ist. (Es gibt Fälle, in denen ObjC etwas mit weniger Codezeilen ausführt, und einige Fälle, in denen C ++ dies mit weniger Codezeilen tut.)

PS Eine weitere Möglichkeit besteht darin, eine .mm-Datei zu verwenden, aber einen Objective C-Wrapper für die Verwendung von std :: string und std :: regex_replace () (oder regex_match ()) zu erstellen.

Volomike
quelle