2012-01-19 25 views
11

En Python, ¿cómo enumerar todos los caracteres que coinciden con la expresión regular extendida POSIX [:space:]?En Python, ¿cómo enumerar todos los caracteres que coinciden con la expresión extendida de POSIX `[: space:]`?

¿Existe una forma programática de extraer los puntos de código Unicode cubiertos por [:space:]?

+0

¿Está utilizando un módulo específico? '\ s' coincide con' \ t \ n \ r \ f \ v'. – charlax

+0

¿Para qué necesita esta información?Si solo es curiosidad, puede grep la base de datos Unicode para todos los caracteres que coincidan con la propiedad de espacios en blanco. El módulo 'Unicodedata' de Python lamentablemente no ofrece una facilidad para enumerar o iterar sobre un conjunto de puntos de código, ciertamente no por propiedad. – tripleee

+0

@Problemaniac, el enlace github está roto – BiGYaN

Respuesta

18

uso de un generador en lugar de una lista por comprensión, y xrange en lugar de range:

>>> s = u''.join(unichr(c) for c in xrange(0x10ffff+1)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <genexpr> 
ValueError: unichr() arg not in range(0x10000) (narrow Python build) 

Whoops: en el uso general sys.maxunicode.

>>> s = u''.join(unichr(c) for c in xrange(sys.maxunicode+1)) 
>>> import re 
>>> re.findall(r'\s', s) 
[u'\t', u'\n', u'\x0b', u'\x0c', u'\r', u' '] 

Whoops: Ummm ¿qué tal "no-break space" etc.?

>>> re.findall(r'\s', chrs, re.UNICODE) 
[u'\t', u'\n', u'\x0b', u'\x0c', u'\r', u'\x1c', u'\x1d', u'\x1e', u'\x1f', u' ' 
, u'\x85', u'\xa0', u'\u1680', u'\u180e', u'\u2000', u'\u2001', u'\u2002', u'\u2 
003', u'\u2004', u'\u2005', u'\u2006', u'\u2007', u'\u2008', u'\u2009', u'\u200a 
', u'\u2028', u'\u2029', u'\u202f', u'\u205f', u'\u3000'] 

¿Qué es todo eso? unicodedata.name es su amigo:

>>> from unicodedata import name 
>>> for c in re.findall(r'\s', chrs, re.UNICODE): 
...  print repr(c), name(c, '') 
... 
u'\t' 
u'\n' 
u'\x0b' 
u'\x0c' 
u'\r' 
u'\x1c' 
u'\x1d' 
u'\x1e' 
u'\x1f' 
u' ' SPACE 
u'\x85' 
u'\xa0' NO-BREAK SPACE 
u'\u1680' OGHAM SPACE MARK 
u'\u180e' MONGOLIAN VOWEL SEPARATOR 
u'\u2000' EN QUAD 
u'\u2001' EM QUAD 
u'\u2002' EN SPACE 
u'\u2003' EM SPACE 
u'\u2004' THREE-PER-EM SPACE 
u'\u2005' FOUR-PER-EM SPACE 
u'\u2006' SIX-PER-EM SPACE 
u'\u2007' FIGURE SPACE 
u'\u2008' PUNCTUATION SPACE 
u'\u2009' THIN SPACE 
u'\u200a' HAIR SPACE 
u'\u2028' LINE SEPARATOR 
u'\u2029' PARAGRAPH SEPARATOR 
u'\u202f' NARROW NO-BREAK SPACE 
u'\u205f' MEDIUM MATHEMATICAL SPACE 
u'\u3000' IDEOGRAPHIC SPACE 
3

Sería un poco difícil ya que Python no es compatible con clases de caracteres POSIX.

El PyPI regex module sí, sin embargo (tiene que instalarlo usted mismo).

La única manera que puedo pensar para extraer todos unicodes que responden a [[:space:]] es un poco feo:

  • generar una cadena de todos los caracteres Unicode
  • de partido contra [[:space:]].

Estoy seguro de que hay una forma mejor de generar stri (la cadena de todos los caracteres Unicode) en mi código a continuación, ¡así que está abierto a la mejora allí!

chrs = [unichr(c) for c in range(0x10ffff+1)] # <-- eww that's not very fast! 
# also we go up to 0x10ffff (inclusive) because that's what help(unichr) says. 
stri = ''.join(chrs) 

import re 
# example if we wanted things matching `\s` with `re` module: 
re.findall('\s',stri) 
# --> [u'\t', u'\n', u'\x0b', u'\x0c', u'\r', u' '] 

# If i had the regex module... 
# regex.findall("[[:space:]]",stri) 

(edit - modificada nombre de variable en str a stri para evitar sobrescribir el str módulo incorporado()!)

+0

¿Cómo no codificar el 'rango (0x10ffff + 1)'? – qazwsx

+0

Entonces, ¿dónde le gustaría que termine el rango? Sin embargo, es problemático porque no todos los puntos de código en el rango son válidos. – tripleee

+0

Bueno, 'help (unichr)' dice 'unichr (i)' válido para '0 <= i <= 0x10ffff' así que no hay problema de que esté codificado. El único problema que tengo es que parece un desperdicio pasar años generando una lista solo para convertirla en una cadena plana, y la generación de la lista ('chrs') parece tomar un segundo o dos notable, solo me pregunto si hay un equivalente de 'string.ascii_letters' para Unicode. –

1

Para actualizar la respuesta para Python 3:

import re 
import sys 

s = ''.join(chr(c) for c in range(sys.maxunicode+1)) 
ws = ''.join(re.findall(r'\s', s)) 
>>> ws.isspace() 
True 

aquí está el caracteres Unicode datapoint encontrados:

>>> ws 
'\t\n\x0b\x0c\r\x1c\x1d\x1e\x1f \x85\xa0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000' 

Y vemos todos estos son considerados como espacios en blanco por el método str.strip():

>>> len(ws.strip()) 
0 

Aquí hay más información sobre los personajes:

from unicodedata import name, category 
for char in ws: 
    print(hex(ord(char)), repr(char), category(char), name(char, None)) 

En Python 3.5, para mí, impresiones:

0x9 '\t' Cc None 
0xa '\n' Cc None 
0xb '\x0b' Cc None 
0xc '\x0c' Cc None 
0xd '\r' Cc None 
0x1c '\x1c' Cc None 
0x1d '\x1d' Cc None 
0x1e '\x1e' Cc None 
0x1f '\x1f' Cc None 
0x20 ' ' Zs SPACE 
0x85 '\x85' Cc None 
0xa0 '\xa0' Zs NO-BREAK SPACE 
0x1680 '\u1680' Zs OGHAM SPACE MARK 
0x2000 '\u2000' Zs EN QUAD 
0x2001 '\u2001' Zs EM QUAD 
0x2002 '\u2002' Zs EN SPACE 
0x2003 '\u2003' Zs EM SPACE 
0x2004 '\u2004' Zs THREE-PER-EM SPACE 
0x2005 '\u2005' Zs FOUR-PER-EM SPACE 
0x2006 '\u2006' Zs SIX-PER-EM SPACE 
0x2007 '\u2007' Zs FIGURE SPACE 
0x2008 '\u2008' Zs PUNCTUATION SPACE 
0x2009 '\u2009' Zs THIN SPACE 
0x200a '\u200a' Zs HAIR SPACE 
0x2028 '\u2028' Zl LINE SEPARATOR 
0x2029 '\u2029' Zp PARAGRAPH SEPARATOR 
0x202f '\u202f' Zs NARROW NO-BREAK SPACE 
0x205f '\u205f' Zs MEDIUM MATHEMATICAL SPACE 
0x3000 '\u3000' Zs IDEOGRAPHIC SPACE 
Cuestiones relacionadas