2010-01-10 7 views
25

Comment puis-je faire correspondre un caractère alpha avec une expression régulière. Je veux un caractère qui est dans \w mais n'est pas dans \d. Je le veux unicode compatible c'est pourquoi je ne peux pas utiliser [a-zA-Z].python-re: Comment faire correspondre un caractère alpha

+1

"unicode compatible" - ce que cela signifie que vous voulez correspondre à la fois e et é, par exemple? – Seth

+0

En Python, n'oubliez pas que pour indiquer une chaîne unicode, vous devez utiliser ceci: u Chaîne Unicode ici '- étant donné que avez-vous essayé str.find() où str est votre chaîne unicode? – Alex

+3

Ce que je voulais dire, c'est que je voulais faire correspondre un, é, あ, 日 나 mais pas 1,. (point), 9, 9, etc. par exemple. – basaundi

Répondre

42

Vos deux premières phrases se contredisent. "dans \w mais n'est pas dans \d" inclut le trait de soulignement. Je suppose de votre troisième phrase que vous ne voulez pas souligner. L'utilisation d'un diagramme de Venn au dos d'une enveloppe aide. Regardons ce que nous ne voulons:

(1) caractères qui ne sont pas couvertes par \w (ne veulent pas tout ce qui est pas alpha, chiffres ou underscore) =>\W
(2) chiffres = >\d
(3) UnderScore =>_

donc ce que nous ne voulons pas quelque chose dans la classe de caractères [\W\d_] et par conséquent ce que nous ne voulons quelque chose dans la classe de caractères [^\W\d_]

Voici un exemple simple (Python 2.6).

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

exploration plus poussée révèle quelques bizarreries de cette approche:

>>> 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 numéral) est considérée comme numérique (d'où il correspond \ w) mais il semble que l'interprète Python " chiffre » pour signifier "chiffre décimal"(catégorie Nd), de sorte qu'il ne correspond pas \ d

U + 2438 (LETTRE PETITE LATIN CERCLÉ Y) ne correspond pas à \ w

Toutes les idéogrammes CJK sont classés en tant que "lettres" et ainsi correspondre \ w

Que l'un des trois points ci-dessus soit préoccupant ou non, cette approche est la meilleure que vous obtiendrez à partir du module re tel qu'il est actuellement publié. La syntaxe comme \ p {lettre} est dans le futur.

+0

Merci! Malgré les bizarreries que vous mentionnez, je pense que je peux commencer à partir d'ici et voir ce que je peux syntoniser. – basaundi

2

Qu'en est-:

\p{L} 

Vous pouvez utiliser ce document comme référence: Unicode Regular Expressions

EDIT: SemblePython doesn't handle Unicode expressions. Jetez un coup d'oeil dans ce lien: Handling Accented Characters with Python Regular Expressions -- [A-Z] just isn't good enough (pas plus actif, un lien vers l'archive internet)

Une autre référence:


Pour la postérité, voici les exemples sur le 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

Merci, mais je ne peux pas savoir si un caractère est un symbole de ponctuation (CJK) ou un symbole numérique autre que 0-9 si je fais une plage comme \ u00E9- \ u00F8. – basaundi

+1

vous pouvez travailler avec des plages de lettres, si vous vous référez à un document comme http://www.tamasoft.co.jp/en/general-info/unicode.html et de choisir toutes les lettres intervalle (qui pourrait être ennuyeux ...) ce lien peut également vous aider: http://kourge.net/projects/regexp-unicode-block –

+0

Un exemple de ceci en action serait utile ici. –

0

Vous pouvez utiliser l'une des expressions suivantes pour correspondre à une seule lettre:

(?![\d_])\w 

ou

\w(?<![\d_]) 

Ici, je correspondent à \w, mais vérifiez que [\d_] ne correspond pas avant/après .

De la documentation:

(?!...) 
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.