2017-09-25 2 views
0

J'effectue une série d'opérations regex sur un fichier texte codé utf-8 qui contient une liste de lignes contenant des caractères alphabétiques et non alphabétiques, y compris les caractères non latins personnages avec des signes diacritiques. Ceci est un extrait du fichier (notez les caractères non latins):Opérations de regex Python 2 à partir de re package ne gère pas le codage diacritique utf-8

oro[=]sia[=]łeś 
oszust[=]ką 

Mon script ouvre d'abord le fichier texte, lit chaque ligne et les caractères inutiles des bandes. Mes opérations regex puis d'abord attraper un mot correspondant à un modèle spécifié, puis soit insérer d'ajuster la position des groupes de caractères non-alphabétiques [=]. Ceci est un extrait de mon script:

# -*- coding: utf-8 -*- 
import re 

with open(r'...\input.txt', "rb") as input, open(r'...\output.txt', "wb") as output: 

for line in input: 

    word = line.strip('\r\n') 

    # Rule 1: ^VCV -> V[=]CV 
    match = re.match('^[AEIOUYaeiouy]([bcćdfghjklłmnńprsśtwzżź]|rz|sz|cz|dz|dż|dź|ch)[aąeęioóuy].*(.*\[=\].*)*', word) 
    result = match.group() if match else None 

    if result == word: 
     word = re.sub('(?<=^[AEIOUYaeiouy])(?=([bcćdfghjklłmnńprsśtwzżź]|rz|sz|cz|dz|dż|dź|ch)[aąeęioóuy])', '[=]', word) 

    outLine = word + "\n"   
    errorList.write(outLine) 

La règle semble échouer avec les entrées avec des environnements de règles qui impliquent des caractères non latins avec des signes diacritiques. Par exemple, lorsque l'entrée de la règle 1 ci-dessus est 'oszust[=]ką', re.match.group() la recode en tant que 'oszust[=]k\xc4'. La conversion du dernier caractère modifie l'environnement et correspond à l'entrée pour l'opération regex suivante.

Le problème réside clairement dans le codage utf-8, car le script parvient à traiter oro[=]sia[=]łeś, où l'environnement de règles ne contient pas de caractères avec des signes diacritiques, très bien. Après avoir lu le site this, j'ai essayé réencoder l'entrée utf-8 afin qu'il réponde à l'environnement pour l'opération de regex, mais j'obtenir cette erreur:

'ascii' codec can't decode byte 0xc4 in position 10: ordinal not in range(128) 

Pourquoi la mention erreur ascii si je suis en train pour l'encoder comme utf-8? Comment puis-je modifier l'encodage pour qu'il corresponde à l'environnement requis pour l'opération regex?

+0

Quelle version python utilisez-vous? Vous pouvez essayer de spécifier un encodage en haut de votre fichier. –

+0

J'utilise Python 2. J'ai oublié d'ajouter la ligne supérieure lorsque je colle mon code dans la question. Le problème persiste même lorsque vous spécifiez # - * - codage: utf-8 - * - dans l'en-tête. –

+0

Vous ne devriez pas ouvrir les fichiers en mode binaire si vous voulez travailler avec des caractères Unicode, sauf si vous êtes prêt à faire le décodage/encodage vous-même. –

Répondre

3

Lorsque vous traitez des caractères Unicode, utilisez des chaînes Unicode. Convertir vers/depuis les chaînes Unicode aux limites d'E/S de votre programme. Passez à la dernière version de Python 3 si possible. Il gère beaucoup mieux Unicode.

# -*- coding: utf-8 -*- 
import re 
import io 

with io.open('input.txt', 'r', encoding='utf8') as input, \ 
    io.open('output.txt', 'w', encoding='utf8') as output: 

    for line in input: 
     word = line.strip() # this will remove all leading/trailing whitespace. 

     # Rule 1: ^VCV -> V[=]CV 
     match = re.match(u'^[AEIOUYaeiouy]([bcćdfghjklłmnńprsśtwzżź]|rz|sz|cz|dz|dż|dź|ch)[aąeęioóuy].*(.*\[=\].*)*', word) 
     result = match.group() if match else None 

     if result == word: 
      word = re.sub(u'(?<=^[AEIOUYaeiouy])(?=([bcćdfghjklłmnńprsśtwzżź]|rz|sz|cz|dz|dż|dź|ch)[aąeęioóuy])', u'[=]', word) 

     outLine = word + u'\n'   
     output.write(outLine) 
+0

Cela a résolu mon problème, merci! –