Регулярные выражения в приложении Objective-C Cocoa


173

Начальный поиск в Google указывает, что в приложении Objective-C Cocoa нет встроенного способа выполнения регулярных выражений.

Итак, четыре вопроса:

  1. Это действительно так?

  2. Ты шутишь, что ли?

  3. Хорошо, тогда есть ли хорошая библиотека с открытым исходным кодом, которую вы рекомендуете?

  4. Как можно приблизиться достаточно близко, не импортируя библиотеку, возможно, с помощью класса NSScanner?


4
Хмммм ... Интересно, что произойдет, если вы используете Monotouch. +1 за вопрос.
Дэн Розенстарк

Ответы:



42
  1. Да, в Какао нет поддержки регулярных выражений. Если вас интересует только логическое соответствие, вы можете использовать NSPredicate, который поддерживает синтаксис регулярных выражений ICU. Но обычно вас интересует положение совпадения или положение подвыражений, и вы не можете получить его с помощью NSPredicate.
  2. Как уже упоминалось, вы можете использовать функции regex POSIX . Но они считаются медленными, и синтаксис регулярных выражений ограничен по сравнению с другими решениями (ICU / pcre ).
  3. Есть много библиотек OSS, CocoaDev имеет обширный список .
  4. Например, RegExKitLite не требует никаких библиотек, просто добавьте .m и .h к вашему проекту.

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


3
Помните, что функции регулярного выражения POSIX не работают с юникодом (только ASCII).
Том Даллинг

К вашему сведению, URL-адрес NSP-предиката является неработающей ссылкой
Taber 12.10.10

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
Мачей Свич

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

19

RegexKit - лучшее, что я нашел. Очень Какао: у. Я использую версию Lite в нескольких наших приложениях для iPhone:

SourceForge

lingonikorg


1
Я второй RegexKit Lite. Очень хорошо!
Дэйв Дрибин

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

12

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

man 3 regex

О, я вижу. это способ сделать это на прямом C, который, вероятно, должен работать в любом приложении Objective-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. Лучшая версия этой инфраструктуры - та, что в IRC-клиенте Colloquy, поскольку она была обновлена ​​для использования PCRE 6.7:

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

Это очень легкий, намного больше, чем RegExKit (хотя, конечно, не так хорошо).


Почему менее способный, если он имеет полное Perl-совместимое регулярное выражение?
ныряет

Связанные вспомогательные методы Objective-C не так обширны, как в RegExKit, но подходят для большинства целей.
Роб Кенигер


5

Во время поиска по этой теме я наткнулся на CocoaOniguruma, который использует Oniguruma , движок регулярных выражений, стоящий за 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 :: string обратно в 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.