Wyrażenia regularne w aplikacji Objective-C Cocoa

173

Początkowe wyszukiwanie w Google wskazuje, że nie ma wbudowanego sposobu wykonywania wyrażeń regularnych w aplikacji Objective-C Cocoa.

A więc cztery pytania:

  1. Czy to prawda?

  2. Czy ty żartujesz?

  3. Ok, więc czy jest jakaś fajna biblioteka open source, którą polecasz?

  4. Jakie są sposoby, aby zbliżyć się wystarczająco blisko bez importowania biblioteki, na przykład z klasą NSScanner?

dreeves
źródło
4
Hmmmm ... Ciekawe, co się stanie, jeśli użyjesz Monotouch. +1 na pytanie.
Dan Rosenstark

Odpowiedzi:

42
  1. Tak, w kakao nie ma obsługi wyrażeń regularnych. Jeśli interesuje Cię tylko dopasowywanie logiczne, możesz użyć NSPredicate, które obsługuje składnię wyrażeń regularnych ICU. Ale zazwyczaj interesuje Cię pozycja dopasowania lub pozycja podwyrażeń i nie możesz tego uzyskać za pomocą NSPredicate.
  2. Jak wspomniano, możesz używać funkcji regex POSIX . Są one jednak uważane za powolne, a składnia wyrażeń regularnych jest ograniczona w porównaniu z innymi rozwiązaniami (ICU / pcre ).
  3. Istnieje wiele bibliotek OSS, CocoaDev ma obszerną listę .
  4. Na przykład RegExKitLite nie wymaga żadnych bibliotek, wystarczy dodać .m i .h do projektu.

    (Moja skarga na RegExKitLite polega na tym, że rozszerza NSString poprzez kategorię, ale można go również uznać za funkcję. Wykorzystuje również niepubliczne biblioteki ICU dostarczane z systemem operacyjnym, co nie jest zalecane przez Apple.)

mfazekas
źródło
3
Należy pamiętać, że funkcje wyrażeń regularnych POSIX nie działają z Unicode (tylko ASCII).
Tom Dalling
Do Twojej wiadomości, że NSPredicate url to uszkodzony link
taber
11
iOS obsługuje wyrażenia regularne do wyszukiwania podciągów, np.[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor
1
Dostępne również w 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
Uważam, że używanie niepublicznych bibliotek ICU jest w porządku, ponieważ jeśli musisz z nich korzystać, dzieje się tak dlatego, że w twojej wersji Cocoa nie ma wbudowanej obsługi wyrażeń regularnych. Jeśli używasz tych bibliotek, oznacza to również, że tworzysz dla starszych systemów, które nie będą już zmieniane, ponieważ nie są obsługiwane. Jeśli tworzysz zarówno dla starego, jak i nowego, używasz RegExKitLite jako rezerwy, jeśli NSRegularExpression nie istnieje. (Tak, wciąż są ludzie pracujący na starszych systemach).
19

RegexKit jest najlepszym, jaki do tej pory znalazłem. Bardzo kakao: y. Używam wersji „Lite” w kilku naszych aplikacjach na iPhone'a:

sourceforge

lingonikorg

avocade
źródło
1
Drugi RegexKit Lite. Bardzo dobrze!
Dave Dribin
1
Fajnie, im więcej ludzi go używa, tym prawdopodobnie będzie lepsze!
awokada
12

Możesz użyć biblioteki wyrażeń regularnych POSIX (Yay dla systemu operacyjnego zgodnego z POSIX). Próbować

man 3 regex
Adam Wright
źródło
rozumiem. jest to sposób na zrobienie tego w prostym C, które prawdopodobnie powinno działać w każdej aplikacji z celem C. fajne dzięki! czy to w zasadzie przyjęty sposób, aby to zrobić?
dreeves
To sposób, który nie wymaga żadnych dodatkowych zależności. Istnieją inne możliwości, jeśli chodzi o biblioteki open source, które można zaimportować (PCRE, dla wyrażeń regularnych Perla, biblioteka Boost RegEx, jeśli używasz Obj-C ++ lub inne wymienione w innych odpowiedziach).
Adam Wright
Jakieś wady mieszania prostego C z Objective-C? Czy mógłbyś dołączyć fragment kodu do konwersji do iz NSString? dzięki jeszcze raz!
dreeves
Objective-C jest zbudowany na C, więc tak naprawdę niczego nie mieszasz. Większość ludzi korzysta jednak z biblioteki, ponieważ oferuje ona interfejs API, który jest łatwiejszy w użyciu.
Marc Charbonneau,
5
A ponieważ funkcje wyrażeń regularnych POSIX działają tylko z łańcuchami ASCII.
Tom Dalling
8

Tanie i brudne rozwiązanie hakerskie, którego używam do rozwiązywania problemów z analizą REGEX i JSON, polega na utworzeniu obiektu UIWebView i wstrzyknięciu funkcji JavaScript w celu wykonania analizy. Następnie funkcja javascript zwraca ciąg z wartością (lub listą wartości), na której mi zależy. W rzeczywistości można przechowywać niewielki zestaw funkcji w bibliotece dostosowanych do określonych zadań, a następnie wywoływać je w razie potrzeby.

Nie wiem, czy ta technika skaluje się do ogromnych ilości powtarzających się żądań analizy, ale w przypadku szybkich transakcji wykonuje zadanie bez konieczności korzystania z dodatkowych zasobów zewnętrznych lub kodu, którego możesz nie rozumieć.

Mark Caufman
źródło
7

Podoba mi się framework AGRegex, który używa PCRE, przydatny, jeśli jesteś przyzwyczajony do składni PCRE. Najlepsza wersja tego frameworka to ta w kliencie Colloquy IRC, ponieważ została zaktualizowana do korzystania z PCRE 6.7:

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

Jest bardzo lekki, znacznie bardziej niż RegExKit (choć oczywiście nie tak wydajny).

Rob Keniger
źródło
Dlaczego mniej wydajne, jeśli ma wyrażenie regularne w pełni zgodne z Perl?
dreeves
Powiązane metody pomocnicze Objective-C nie są tak obszerne, jak te w RegExKit, jednak są dobre w większości zastosowań.
Rob Keniger
6

NSRegularExpression jest dostępny od wersji Mac OS X 10.7 i IOS 4.0.

bbaassssiiee
źródło
5

Podczas moich poszukiwań na ten temat natknąłem się na CocoaOniguruma, która używa Oniguruma , silnika wyrażeń regularnych za Ruby 1.9 i PHP5. Wydaje się nieco nowszy w porównaniu do istniejącego OregKit (po japońsku). Nie wiem, jak wypadają na tle innych wiązań.

Newtonapple
źródło
4

Googling alittle, znalazłem tę bibliotekę: RegexOnNSString

Biblioteka open source zawierająca funkcje takie jak:

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

i używając NSRegularExpressionclass. Dość łatwy w użyciu i nie musisz się o nic martwić.

Należy pamiętać, że NSRegularExpressionjest on dostępny od wersji Mac OS X 10.7 i IOS 4.0, jak wspomniano w Datasmid.

nickeyzzz
źródło
1

Ułatwiam to. Dodaję nowy plik C ++ do mojego projektu Objective C, zmieniam jego nazwę na .mm, a następnie tworzę w nim standardową klasę C ++. Następnie tworzę statyczną metodę klasy w sekcji "public:" dla funkcji C ++, która pobiera NSString i zwraca NSString (lub NSArray, jeśli tego chcesz). Następnie konwertuję NSString na C ++ std :: string w następujący sposób:

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

Stamtąd mogę użyć regex_replace w następujący sposób:

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

Następnie mogę przekonwertować ten std :: string z powrotem na NSString za pomocą:

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

Jeśli używasz tego języka C ++ tylko dla tej funkcji, możesz uznać za stosowne wywołanie tego pliku extra.mm (nazwa klasy Extra) i umieszczenie tej statycznej metody klasy w, a następnie dodanie innych statycznych metod klasy, gdy nadejdzie sytuacja gdzie po prostu ma sens robienie tego w C ++, ponieważ w niektórych przypadkach jest to mniej kłopotliwe. (Są przypadki, w których ObjC robi coś z mniejszą liczbą wierszy kodu i niektóre przypadki, w których C ++ robi to z mniejszą liczbą wierszy kodu).

PS Jeszcze innym sposobem jest użycie pliku .mm, ale utworzenie opakowania Objective C wokół użycia std :: string i std :: regex_replace () (lub regex_match ()).

Volomike
źródło