Expresiones regulares en una aplicación Objective-C Cocoa


173

Google inicial indica que no hay una forma integrada de hacer expresiones regulares en una aplicación Objective-C Cocoa.

Entonces cuatro preguntas:

  1. ¿Es eso realmente cierto?

  2. ¿Me estás tomando el pelo?

  3. Ok, ¿hay una buena biblioteca de código abierto que recomiendas?

  4. ¿Cuáles son las formas de acercarse lo suficiente sin importar una biblioteca, tal vez con la clase NSScanner?


44
Hmmmm ... Me pregunto qué pasará si usas Monotouch. +1 para la pregunta.
Dan Rosenstark

Respuestas:



42
  1. Sí, no hay soporte para expresiones regulares en Cocoa. Si solo le interesa la coincidencia booleana, puede usar NSPredicate, que admite la sintaxis de expresiones regulares de la UCI. Pero generalmente le interesa la posición de la coincidencia o la posición de las subexpresiones, y no puede obtenerla con NSPredicate.
  2. Como se mencionó, puede usar las funciones de expresiones regulares POSIX . Pero se consideran lentos y la sintaxis de expresiones regulares es limitada en comparación con otras soluciones (UCI / pcre ).
  3. Hay muchas bibliotecas OSS, CocoaDev tiene una extensa lista .
  4. RegExKitLite, por ejemplo, no requiere ninguna biblioteca, solo agregue .my .h a su proyecto.

    (Mi queja contra RegExKitLite es que extiende NSString a través de la categoría, pero también puede considerarse como una característica. También utiliza las bibliotecas de ICU no públicas que se envían con el sistema operativo, lo cual no es recomendado por Apple).


3
Tenga en cuenta que las funciones de expresiones regulares POSIX no funcionan con Unicode (solo ASCII).
Tom Dalling

FYI que NSPredicate url es un enlace roto
taber

11
iOS admite expresiones regulares para búsquedas de subcadenas, por ejemplo[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor

1
También disponible en 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

Me parece bien usar bibliotecas de UCI no públicas, porque si necesita usarlo, es porque no hay soporte de expresiones regulares incorporado en su versión de Cocoa. Si usa esas bibliotecas, también significa que está compilando para sistemas más antiguos, que ya no se cambiarán ya que no son compatibles. Si está compilando para viejos y nuevos, use RegExKitLite como reserva si NSRegularExpression no existe. (Sí, todavía hay personas trabajando en sistemas más antiguos).

19

RegexKit es el mejor que he encontrado hasta ahora. Muy cacao: y. Estoy usando la versión "Lite" en varias de nuestras aplicaciones para iPhone:

sourceforge

lingonikorg


1
Yo segundo RegexKit Lite. ¡Muy agradable!
Dave Dribin el

1
¡Genial, cuantas más personas lo usen, mejor será probablemente!
avocade

12

Puede usar la biblioteca de expresiones regulares POSIX (Yay para un sistema operativo compatible con POSIX). Tratar

man 3 regex

Oh ya veo. Esta es una manera de hacerlo en C directo, que presumiblemente debería funcionar en cualquier aplicación de Objective-C. ¡Genial, gracias! ¿Esa es básicamente la forma aceptada de hacer esto?
Dreeves

Es una forma, que no requiere ninguna dependencia adicional. Hay otras opciones, en términos de bibliotecas de código abierto que podría importar (PCRE, para expresiones regulares de Perl, la biblioteca The Boost RegEx si está usando Obj-C ++ u otras que figuran en otras respuestas).
Adam Wright el

¿Alguna desventaja de mezclar directamente C con Objective-C? ¿Podría incluir un fragmento de código para convertir ay desde NSString? ¡gracias de nuevo!
Dreeves

Objective-C está construido sobre C, por lo que realmente no estás mezclando nada. Sin embargo, la mayoría de las personas usan una biblioteca, ya que ofrece una API que es más fácil de usar.
Marc Charbonneau

55
Y debido a que las funciones de expresiones regulares POSIX solo funcionan con cadenas ASCII.
Tom Dalling

8

La solución de pirateo barata y sucia que uso para resolver los problemas de análisis de REGEX y JSON es crear un objeto UIWebView e inyectar funciones de Javascript para realizar el análisis. La función de JavaScript luego devuelve una cadena del valor (o lista de valores) que me interesa. De hecho, puede almacenar un pequeño conjunto de funciones de biblioteca personalizadas para tareas particulares y luego simplemente llamarlas según sea necesario.

No sé si esta técnica escala a grandes volúmenes de solicitudes de análisis repetidas, pero para cosas transaccionales rápidas hace el trabajo sin depender de ningún recurso externo adicional o código que quizás no entiendas.


7

Me gusta el marco AGRegex que usa PCRE, útil si está acostumbrado a la sintaxis PCRE. La mejor versión de este marco es la del cliente Colloquy IRC, ya que se ha actualizado para usar PCRE 6.7:

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

Es muy liviano, mucho más que RegExKit (aunque, por supuesto, no es tan capaz).


¿Por qué menos capaz si tiene expresiones regulares compatibles con Perl?
Dreeves

Los métodos de ayuda Objective-C asociados no son tan extensos como los de RegExKit, sin embargo, están bien para la mayoría de los propósitos.
Rob Keniger


5

Durante mi búsqueda sobre este tema, me encontré con CocoaOniguruma que usa Oniguruma , el motor de Expresión Regular detrás de Ruby1.9 y PHP5. Parece un poco más nuevo en comparación con el OregonKit existente (en japonés). No estoy seguro de cómo se comparan con otros enlaces.


4

Buscando un poco en Google, encontré esta biblioteca: RegexOnNSString

Biblioteca de código abierto, que contiene funciones como:

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

y usando NSRegularExpressionclase. Muy fácil de usar y sin necesidad de preocuparse por nada.

Tenga en cuenta que NSRegularExpressionestá disponible desde Mac OS X v10.7 e IOS 4.0, como mencionó Datasmid.


1

Yo te lo pongo fácil. Agrego un nuevo archivo C ++ a mi proyecto Objective C, lo renombro como .mm y luego creo una clase C ++ estándar dentro. Luego, hago un método de clase estática en la sección "public:" para una función C ++ que toma un NSString y devuelve un NSString (o NSArray, si eso es lo que quieres). Luego convierto NSString a C ++ std :: string así:

// 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 de ahí, puedo usar regex_replace así:

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

Entonces, puedo convertir ese std :: string nuevamente en un NSString con:

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

Si solo está usando este C ++ solo para esta función, puede que le resulte adecuado llamar a este archivo extra.mm (nombre de clase Extra) y poner este método de clase estática, y luego agregar otros métodos de clase estática cuando llegue la situación donde tiene sentido hacerlo en C ++ porque es menos complicado en algunos casos. (Hay casos donde ObjC hace algo con menos líneas de código, y algunos casos donde C ++ lo hace con menos líneas de código).

PD Aún otra forma de hacerlo es usar un archivo .mm pero hacer un contenedor de Objective C alrededor del uso de std :: string y std :: regex_replace () (o regex_match ()).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.