2012-01-04 9 views
7

Hola, estoy usando la biblioteca Regex estándar (regcomp, regexec ..). Pero ahora bajo demanda debería agregar soporte unicode a mis códigos para expresiones regulares.¿POSIX regex.h proporciona caracteres unicode o básicamente no ascii?

¿Standard Regex Library proporciona caracteres unicode o básicamente no ascii? Investigué en la Web y pienso que no.

Mi proyecto es crítico de recursos, por lo tanto, no quiero utilizar grandes bibliotecas para él (ICU y Boost.Regex).

Cualquier ayuda se agradece ..

+1

No lo sé, pero la biblioteca de regex del plan 9 es; un puerto de Unix está en http://swtch.com/plan9port/unix/ bajo 'libregexp9' – Dave

Respuesta

6

Parece que POSIX Regex funciona correctamente con la configuración regional UTF-8. Acabo de escribir una prueba simple (ver abajo) y la usé para hacer coincidir una cadena con caracteres cirílicos contra la expresión regular "[[:alpha:]]" (por ejemplo). Y todo funciona bien.

Nota: Lo más importante que debe recordar: las funciones de expresiones regulares están relacionadas con la configuración regional. Entonces debe llamar al setlocale() antes que él.

#include <sys/types.h> 
#include <string.h> 
#include <regex.h> 
#include <stdio.h> 
#include <locale.h> 

int main(int argc, char** argv) { 
    int ret; 
    regex_t reg; 
    regmatch_t matches[10]; 

    if (argc != 3) { 
    fprintf(stderr, "Usage: %s regex string\n", argv[0]); 
    return 1; 
    } 

    setlocale(LC_ALL, ""); /* Use system locale instead of default "C" */ 

    if ((ret = regcomp(&reg, argv[1], 0)) != 0) { 
    char buf[256]; 
    regerror(ret, &reg, buf, sizeof(buf)); 
    fprintf(stderr, "regcomp() error (%d): %s\n", ret, buf); 
    return 1; 
    } 

    if ((ret = regexec(&reg, argv[2], 10, matches, 0)) == 0) { 
    int i; 
    char buf[256]; 
    int size; 
    for (i = 0; i < sizeof(matches)/sizeof(regmatch_t); i++) { 
     if (matches[i].rm_so == -1) break; 
     size = matches[i].rm_eo - matches[i].rm_so; 
     if (size >= sizeof(buf)) { 
     fprintf(stderr, "match (%d-%d) is too long (%d)\n", 
       matches[i].rm_so, matches[i].rm_eo, size); 
     continue; 
     } 
     buf[size] = '\0'; 
     printf("%d: %d-%d: '%s'\n", i, matches[i].rm_so, matches[i].rm_eo, 
      strncpy(buf, argv[2] + matches[i].rm_so, size)); 

    } 
    } 

    return 0; 
} 

Ejemplo de uso:

$ locale 
LANG=ru_RU.UTF-8 
LC_CTYPE="ru_RU.UTF-8" 
LC_COLLATE="ru_RU.UTF-8" 
... (skip) 
LC_ALL= 
$ ./reg '[[:alpha:]]' ' 359 фыва' 
0: 5-7: 'ф' 
$ 

La longitud del resultado de la casación es de dos bytes porque cartas cirílico en UTF-8 toma tanto.

+0

creo que me malinterpretas. Quiero hacer eso: ./reg 'ç' 'çilek45' – iyasar

+0

¿Cuál es el problema? El código de arriba imprime: '0: 0-2: 'ç'' con sus parámetros. Es decir, funciona –

+0

lo siento, mi error funciona ... – iyasar

6

Básicamente, expresiones regulares POSIX no son conscientes de Unicode. Puede tratar de usarlos en caracteres Unicode, pero puede haber problemas con glifos que tienen codificaciones múltiples y otros problemas similares que manejan las bibliotecas conscientes de Unicode.

de la norma, IEEE Std 1003.1-2008:

Matching se basa en el patrón de bits utilizados para codificar el carácter, no en la representación gráfica del personaje. Esto significa que si un conjunto de caracteres contiene dos o más codificaciones para un símbolo gráfico, o si las cadenas buscadas contienen texto codificado en más de un conjunto de códigos, no se intenta buscar ninguna otra representación del símbolo codificado. Si es necesario, el usuario puede especificar clases de equivalencia que contengan todas las variaciones del símbolo gráfico deseado.

Tal vez libpcre funcionaría para usted? Es un poco más pesado que las expresiones regulares POSIX, pero creo que es más ligero que ICU o Boost.

0

Si realmente quiere decir "Estándar", es decir, std::regex de C++ 11, entonces todo lo que necesita hacer es cambiar a std::wregex (y std::wstring por supuesto).

+0

Están hablando de la interfaz del sistema regex.h como lo especifica el estándar POSIX – Spookbuster

Cuestiones relacionadas