2010-01-10 10 views
25

¿Cómo puedo unir un carácter alfabético con una expresión regular? Quiero un personaje que está en \w pero no está en \d. Lo quiero compatible con Unicode por eso no puedo usar [a-zA-Z].python-re: cómo puedo unir un carácter alfabético

+1

"compatible con Unicode" - ¿quiere decir que desea hacer coincidir tanto E y E, por ejemplo? – Seth

+0

En Python, recuerde que para indicar una cadena Unicode debe usar esto: u'Unicode string here '- dado que ha probado str.find() donde str es su cadena Unicode? – Alex

+3

Lo que quise decir es que quería hacer coincidir a, é, あ, 日 나 pero no 1,. (punto), 9, 9, etc. etc. por ejemplo. – basaundi

Respuesta

42

Las dos primeras oraciones se contradicen entre sí. "en \w pero no está en \d" incluye subrayado. De su tercera oración supongo que no quiere subrayar.

El uso de un diagrama de Venn en la parte posterior de un sobre ayuda. Veamos lo que no queremos:

(1) caracteres que no son igualados por \w (es decir, no quieren nada que no sea alfa, dígitos o subrayado) =>\W
(2) dígitos = >\d
(3) subrayan =>_

Entonces, lo que no queremos es que nada en la clase de caracteres [\W\d_] y por lo tanto lo que queremos es nada en la clase de caracteres [^\W\d_]

Aquí está un ejemplo sencillo (Python 2.6).

>>> import re 
>>> rx = re.compile("[^\W\d_]+", re.UNICODE) 
>>> rx.findall(u"abc_def,k9") 
[u'abc', u'def', u'k'] 

La exploración adicional revela algunas peculiaridades de este enfoque:

>>> import unicodedata as ucd 
>>> allsorts =u"\u0473\u0660\u06c9\u24e8\u4e0a\u3020\u3021" 
>>> for x in allsorts: 
...  print repr(x), ucd.category(x), ucd.name(x) 
... 
u'\u0473' Ll CYRILLIC SMALL LETTER FITA 
u'\u0660' Nd ARABIC-INDIC DIGIT ZERO 
u'\u06c9' Lo ARABIC LETTER KIRGHIZ YU 
u'\u24e8' So CIRCLED LATIN SMALL LETTER Y 
u'\u4e0a' Lo CJK UNIFIED IDEOGRAPH-4E0A 
u'\u3020' So POSTAL MARK FACE 
u'\u3021' Nl HANGZHOU NUMERAL ONE 
>>> rx.findall(allsorts) 
[u'\u0473', u'\u06c9', u'\u4e0a', u'\u3021'] 

U + 3021 (Hangzhou numeral) se trata como numérico (de ahí que coincide con \ w) pero parece que interpreta Python " dígito" en el sentido de 'dígito decimal' (categoría Nd) por lo que no coincide con \ d

U + 2438 (en el círculo LETRA LATINA Y) no coincide con \ w

ideogramas

Todo CJC se clasifican como "letras" y por lo tanto coinciden \ w

Si cualquiera de los 3 puntos anteriores son una preocupación o no, ese enfoque es el mejor que obtendrá del módulo de revisión tal como está publicado actualmente. La sintaxis como \ p {letter} está en el futuro.

+0

¡Gracias! A pesar de las peculiaridades que mencionas, creo que puedo comenzar desde aquí y ver qué puedo sintonizar. – basaundi

2

¿Qué hay de:

\p{L} 

Usted puede utilizar este documento como referencia: Unicode Regular Expressions

EDIT: ParecePython doesn't handle Unicode expressions. Echar un vistazo a este enlace: Handling Accented Characters with Python Regular Expressions -- [A-Z] just isn't good enough (ya no está activa, enlace al archivo de Internet)

Otras referencias:


Para posteridad, aquí están los ejemplos en el blog:

import re 
string = 'riché' 
print string 
riché 

richre = re.compile('([A-z]+)') 
match = richre.match(string) 
print match.groups() 
('rich',) 

richre = re.compile('(\w+)',re.LOCALE) 
match = richre.match(string) 
print match.groups() 
('rich',) 

richre = re.compile('([é\w]+)') 
match = richre.match(string) 
print match.groups() 
('rich\xe9',) 

richre = re.compile('([\xe9\w]+)') 
match = richre.match(string) 
print match.groups() 
('rich\xe9',) 

richre = re.compile('([\xe9-\xf8\w]+)') 
match = richre.match(string) 
print match.groups() 
('rich\xe9',) 

string = 'richéñ' 
match = richre.match(string) 
print match.groups() 
('rich\xe9\xf1',) 

richre = re.compile('([\u00E9-\u00F8\w]+)') 
print match.groups() 
('rich\xe9\xf1',) 

matched = match.group(1) 
print matched 
richéñ 
+1

Gracias, pero no sé si un personaje es un símbolo de puntuación (CJK) o un símbolo numérico distinto de 0-9 si hago un rango como \ u00E9- \ u00F8. – basaundi

+1

puede trabajar con rangos de letras, si se refiere a un documento como http://www.tamasoft.co.jp/en/general-info/unicode.html y para seleccionar el intervalo de todas las letras (que podría ser aburrido ...); este enlace también puede ayudarlo: http://kourge.net/projects/regexp-unicode-block –

+0

Un ejemplo de esto en acción sería útil aquí. –

0

Puede utilizar una de las siguientes expresiones para que coincida con una sola letra:

(?![\d_])\w 

o

\w(?<![\d_]) 

Aquí fósforo para \w, pero compruebe que [\d_] no se corresponde antes/después de eso .

A partir de los documentos:

(?!...) 
Matches if ... doesn’t match next. This is a negative lookahead assertion. For example, Isaac (?!Asimov) will match 'Isaac ' only if it’s not followed by 'Asimov'. 

(?<!...) 
Matches if the current position in the string is not preceded by a match for .... This is called a negative lookbehind assertion. Similar to positive lookbehind assertions, the contained pattern must only match strings of some fixed length and shouldn’t contain group references. Patterns which start with negative lookbehind assertions may match at the beginning of the string being searched. 
Cuestiones relacionadas