Expressões regulares em um aplicativo Objective-C Cocoa

173

A pesquisa inicial indica que não há uma maneira integrada de fazer expressões regulares em um aplicativo Objective-C Cocoa.

Então, quatro perguntas:

  1. Isso é mesmo verdade?

  2. Você está brincando comigo?

  3. Ok, existe uma boa biblioteca de código aberto que você recomenda?

  4. Quais são as maneiras de se aproximar o suficiente sem importar uma biblioteca, talvez com a classe NSScanner?

dreeves
fonte
4
Hmmmm ... Gostaria de saber o que acontece se você usar o Monotouch. +1 para a pergunta.
Dan Rosenstark

Respostas:

141

Percebi que, a partir do iOS 4.0, a Apple fornece uma classe NSRegularExpression . Além disso, a partir de 10.7, a classe está disponível no OS X .

Philip Jespersen
fonte
11
agora Mac OS X 10.7 agora
user102008
42
  1. Sim, não há suporte a regex no cacau. Se você estiver interessado apenas na correspondência booleana, poderá usar o NSPredicate que suporta a sintaxe regex ICU. Mas geralmente você está interessado na posição da correspondência ou na posição das subexpressões e não pode obtê-lo com o NSPredicate.
  2. Como mencionado, você pode usar as funções regex POSIX . Mas eles são considerados lentos e a sintaxe regex é limitada em comparação com outras soluções (ICU / pcre ).
  3. Existem muitas bibliotecas OSS, o CocoaDev possui uma extensa lista .
  4. O RegExKitLite, por exemplo, não requer nenhuma biblioteca, basta adicionar o .m e .h ao seu projeto.

    (Minha reclamação contra o RegExKitLite é que ela estende o NSString por categoria, mas também pode ser considerado um recurso. Também usa as bibliotecas ICU não públicas fornecidas com o sistema operacional, o que não é recomendado pela Apple.)

mfazekas
fonte
3
Lembre-se de que as funções regex POSIX não funcionam com unicode (apenas ASCII).
Tom Dalling
FYI que NSPredicate URL é um link quebrado
taber
11
O iOS suporta expressões regulares para pesquisas de substring, por exemplo,[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor
1
Também disponível no 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
Acho bom usar bibliotecas ICU não públicas, porque se você precisar usá-las, é porque não há suporte a regex interno na sua versão do Cocoa. Se você usar essas bibliotecas, isso também significa que você está construindo para sistemas mais antigos, que não serão mais alterados porque não são suportados. Se você estiver criando para o antigo e o novo, use o RegExKitLite como fallback se o NSRegularExpression não existir. (Sim, ainda existem pessoas trabalhando em sistemas mais antigos).
19

O RegexKit é o melhor que eu já encontrei. Muito cacau: y. Estou usando a versão "Lite" em vários de nossos aplicativos para iPhone:

sourceforge

lingonikorg

avocade
fonte
1
Eu segundo RegexKit Lite. Muito agradável!
Dave Dribin
1
Legal, quanto mais pessoas o usarem, melhor provavelmente se tornará!
avocade 12/01/09
12

Você pode usar a biblioteca de expressões regulares do POSIX (Yay para um sistema operacional compatível com POSIX). Experimentar

man 3 regex
Adam Wright
fonte
Ah eu vejo. essa é uma maneira de fazê-lo em C direto, que provavelmente deve funcionar em qualquer aplicativo de objetivo-C. legal, obrigado! Essa é basicamente a maneira aceita de fazer isso?
dreeves
É uma maneira, que não requer nenhuma dependência adicional. Existem outras opções, em termos de bibliotecas de código aberto que você pode importar (PCRE, para regexes Perl, biblioteca The Boost RegEx, se você estiver usando Obj-C ++, ou outros listados em outras respostas).
237 Adam Adam Wright
Alguma desvantagem em misturar C direto com Objective-C? Você poderia incluir um trecho de código para converter de e para o NSString? obrigado novamente!
dreeves
Objective-C é construído sobre C, então você não está realmente misturando nada. A maioria das pessoas usa uma biblioteca, pois ela oferece uma API mais fácil de usar.
Marc Charbonneau
5
E como as funções regex POSIX funcionam apenas com cadeias ASCII.
Tom Dalling
8

A solução barata e suja de hack que eu uso para resolver problemas de análise REGEX e JSON é criar um objeto UIWebView e injetar funções de Javascript para fazer a análise. A função javascript retorna uma sequência do valor (ou lista de valores) com que me preocupo. De fato, você pode armazenar um pequeno conjunto de funções de biblioteca personalizadas para tarefas específicas e depois chamá-las conforme necessário.

Não sei se essa técnica é dimensionada para grandes volumes de solicitações de análise repetidas, mas para coisas transacionais rápidas, ele faz o trabalho sem depender de recursos ou códigos externos extras que você talvez não entenda.

Mark Caufman
fonte
7

Gosto da estrutura AGRegex que usa PCRE, útil se você estiver acostumado com a sintaxe PCRE. A melhor versão dessa estrutura é a do cliente Colloquy IRC, pois foi atualizada para usar o PCRE 6.7:

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

É muito leve, muito mais que o RegExKit (embora não seja tão capaz, é claro).

Rob Keniger
fonte
Por que menos capaz se tiver um regex compatível com perl completo?
dreeves
Os métodos auxiliares Objective-C associados não são tão extensos quanto os do RegExKit, mas são adequados para a maioria dos propósitos.
Rob Keniger
6

NSRegularExpression está disponível desde o Mac OS X v10.7 e IOS 4.0.

bbaassssiiee
fonte
5

Durante minha pesquisa neste tópico, deparei-me com o CocoaOniguruma, que usa o Oniguruma , o mecanismo de Expressão Regular por trás do Ruby1.9 e PHP5. Parece um pouco mais recente em comparação com o OregKit existente (em japonês). Não tenho certeza de como eles se comparam com outras ligações.

newtonapple
fonte
4

Pesquisando um pouco, encontrei esta biblioteca: RegexOnNSString

Biblioteca de código aberto, contendo funções como:

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

e usando NSRegularExpressionclasse. Muito fácil de usar e não precisa se preocupar com nada.

Observe que NSRegularExpressionestá disponível desde o Mac OS X v10.7 e IOS 4.0, como o Datasmid mencionado.

nickeyzzz
fonte
1

Eu facilito. Eu adiciono um novo arquivo C ++ ao meu projeto do Objective C, renomeio para .mm e, em seguida, crio uma classe C ++ padrão dentro. Em seguida, crio um método de classe estática na seção "public:" para uma função C ++ que pega um NSString e retorna um NSString (ou NSArray, se é isso que você deseja). Em seguida, converto o NSString em C ++ std :: string da seguinte forma:

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

A partir daí, eu posso usar regex_replace da seguinte maneira:

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

Em seguida, posso converter essa std :: string novamente em um NSString com:

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

Se você estiver usando apenas este C ++ apenas para esta função, poderá achar adequado chamar esse arquivo extra.mm (nome da classe Extra) e colocar esse método de classe estática e adicionar outros métodos de classe estática quando a situação chegar onde faz sentido fazê-lo em C ++, porque é menos problemático em alguns casos. (Há casos em que o ObjC faz algo com menos linhas de código e alguns casos em que o C ++ faz com menos linhas de código.)

PS Ainda outra maneira disso é usar um arquivo .mm, mas criar um wrapper de Objective C em torno do uso de std :: string e std :: regex_replace () (ou regex_match ()).

Volomike
fonte