Регулярні вирази у програмі "Какао" Objective-C


173

Початковий Googling вказує на те, що в додатку Objective-C Cocoa немає вбудованого способу регулярних виразів.

Отже чотири питання:

  1. Це справді правда?

  2. Ти мене жартуєш?

  3. Гаразд, чи є приємна бібліотека з відкритим кодом, яку ви рекомендуєте?

  4. Які способи наблизитися без імпорту бібліотеки, можливо, з класом NSScanner?


4
Хм-м-м ... Цікаво, що станеться, якщо використовувати Monotouch. +1 для запитання.
Дан Розенстарк

Відповіді:



42
  1. Так, у какао немає підтримки для регулярних виразів. Якщо вас цікавить лише булева відповідність, ви можете використовувати NSPredicate, який підтримує синтаксис регулярного вирівнювання ICU. Але, як правило, вас цікавить позиція збігу або позиція підвиразів, і ви не можете отримати це за допомогою NSPredicate.
  2. Як вже згадувалося, ви можете використовувати функції регулярного вираження POSIX . Але вони вважаються повільними, і синтаксис регулярного вираження обмежений порівняно з іншими рішеннями (ICU / pcre ).
  3. Бібліотеки OSS багато, у CocoaDev є великий список .
  4. Наприклад, RegExKitLite не вимагає бібліотек, просто додайте .m та .h до свого проекту.

    (Моя скарга на RegExKitLite полягає в тому, що він розширює NSString через категорію, але це також може розглядатися як особливість. Також він використовує непублічні бібліотеки ICU, що постачаються з ОС, що не рекомендується Apple.)


3
Майте на увазі, що функції регулярного вираження POSIX не працюють з unicode (лише ASCII).
Том Даллінг

FYI, що URL-адреса NSPredicate - це непрацездатне посилання
taber

11
iOS підтримує регулярні вирази для пошуку підрядків, наприклад[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor

1
Також доступний у 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

Я вважаю прекрасним використання непублічних бібліотек ICU, тому що якщо вам потрібно використовувати, це тому, що у вашій версії Cocoa немає вбудованої підтримки регулярного виразів. Якщо ви використовуєте ці бібліотеки, це також означає, що ви будуєте для старих систем, які більше не змінюватимуться, оскільки вони не підтримуються. Якщо ви будуєте і для старих, і для нових, ви використовуєте RegExKitLite як резервний, якщо NSRegularExpression не існує. (Так, все ще є люди, які працюють над старими системами).

19

RegexKit - найкраще, що я знайшов. Дуже какао: у. Я використовую версію "Lite" у кількох наших додатках для iPhone:

sourceforge

lingonikorg


1
Я другий RegexKit Lite. Дуже хороша!
Дейв Дрибін

1
Класно, чим більше людей, які ним користуються, тим краще, напевно, стане!
авокада

12

Ви можете використовувати бібліотеку регулярних виразів POSIX (Yay для ОС, сумісної з POSIX). Спробуйте

man 3 regex

о Я бачу. це спосіб зробити це в прямому C, який, імовірно, повинен працювати в будь-якому додатку з об'єктивним С. класно, дякую! це в основному прийнятий спосіб зробити це?
дрів

Це спосіб, який не потребує додаткових залежностей. Є й інші варіанти, що стосуються бібліотек з відкритим кодом, які ви можете імпортувати (PCRE, для регексів Perl, бібліотеки Boost RegEx, якщо ви використовуєте Obj-C ++ або інші, перелічені в інших відповідях).
Адам Райт

Якісь недоліки в змішуванні прямої C з Objective-C? Чи можете ви включити фрагмент коду для перетворення в NSString і з нього? знову дякую!
дерев

Objective-C побудований на вершині C, тому ви насправді нічого не змішуєте. Однак більшість людей користується бібліотекою, оскільки вона пропонує простіший у користуванні API.
Марк Шарбонно

5
А тому, що функції регулярного вираження POSIX працюють лише з рядками ASCII.
Том Даллінг

8

Дешеве і брудне рішення для злому, яке я використовую для вирішення проблем розбору REGEX та JSON, полягає у створенні об'єкта UIWebView та введенні функцій Javascript для розбору. Потім функція javascript повертає рядок значення (або список значень), який мені важливий. Насправді ви можете зберігати невеликий набір бібліотеки функцій, налаштованих під конкретні завдання, а потім просто викликати їх за потребою.

Я не знаю, чи застосовується ця методика до величезних обсягів повторних запитів на розбір, але для швидкого трансакційного завдання вона виконує роботу, не залежно від зайвих зовнішніх ресурсів чи коду, які ви, можливо, не зрозумієте.


7

Мені подобається структура AGRegex, яка використовує PCRE, зручна, якщо ви звикли до синтаксису PCRE. Найкращою версією цієї рамки є версія для клієнта Colloquy IRC, оскільки вона була модернізована до використання PCRE 6.7:

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

Він дуже легкий, набагато більше, ніж RegExKit (хоча, звичайно, не такий, як здатний).


Чому менш дієздатний, якщо має повний сумісний з Perl регулярний вираз?
дрів

Асоційовані допоміжні методи Objective-C не є настільки обширними, як у RegExKit, однак вони підходять для більшості цілей.
Роб Кенігер


5

Під час пошуку в цій темі я натрапив на CocoaOniguruma, який використовує Oniguruma , двигун Regular Expression за Ruby1.9 та PHP5. Це здається дещо новішим порівняно з існуючим OregKit (японською). Не впевнені, як вони складаються проти інших прив'язок.


4

Гугл аліт , знайшов цю бібліотеку: RegexOnNSString

Бібліотека з відкритим кодом, що містить такі функції, як:

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

та використання NSRegularExpressionкласу. Досить проста у використанні і не потрібно нічого турбуватися.

Зверніть увагу, що NSRegularExpressionце доступно з Mac OS X v10.7 та IOS 4.0, як згадується Datasmid.


1

Я полегшу. Я додаю новий файл C ++ до свого проекту Objective C, перейменую його як .mm, а потім створюю всередині стандартний клас C ++. Потім я роблю метод статичного класу в розділі "public:" для функції C ++, який приймає NSString і повертає NSString (або NSArray, якщо це те, що ти хочеш). Потім я конвертую NSString в C ++ std :: string так:

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

Звідти я можу використовувати regex_replace так:

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

Тоді я можу перетворити ту строку std :: назад у NSString за допомогою:

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

Якщо ви використовуєте цей C ++ лише для цієї функції, то, можливо, вам буде доречно викликати цей файл extra.mm (ім'я класу Extra) та ввести цей метод статичного класу, а потім додати інші методи статичного класу, коли ситуація настане де це просто має сенс робити це на C ++, оскільки в деяких випадках це менше клопоту. (Бувають випадки, коли ObjC робить щось із меншим рядком коду, і деякі випадки, коли C ++ робить це з меншими рядками коду.)

PS Ще одним іншим способом для цього є використання .mm-файлу, але зробити обертку Objective C навколо використання std :: string та std :: regex_replace () (або regex_match ()).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.