2012-01-21 13 views
12

Ubuntu'daki sensors yardımcı programının çıktısı için basit bir normal ifade ayrıştırıcısı yazıyorum. İşte ayrıştırma metin satırı bir örnek:(Unicode) derece sembolünü normal ifadelerle nasıl ayrıştırılabilir?

temp1:  +31.0°C (crit = +107.0°C) 

Ve burada ki (Python) eşleşecek şekilde kullanıyorum regex var:

temp_re = re.compile(r'(temp1:)\s+(\+|-)(\d+\.\d+)\W\WC\s+' 
        r'\(crit\s+=\s+(\+|-)(\d+\.\d+)\W\WC\).*') 

Bu kod beklenen ve maçları işler olarak yukarıda verdiğim örnek metin. Ben gerçekten ilgilendiğim tek bit sayılardır, bu nedenle bu biraz:

+ veya - işareti eşleştirerek başlar ve °C eşleştirerek biter
(\+|-)(\d+\.\d+)\W\WC 

.

Sorunuz, neden iki \W (alfasayısal olmayan) karakterin neden bir yerine ° eşleşmesidir? Unicode'un benim için farklı olarak temsil edildiği sistemlerde kod kırılacak mı? Eğer öyleyse, nasıl taşınabilir yapabilirim?

+2

"re.UNICODE" bayrağını deneyin – netvope

+0

"re.UNICODE" bayrağı ile RE, "\ W \ WC" veya "\ WC" ile eşleşmiyor. Ya da seni yanlış anladım mı? – snim2

+1

Ayrıca ssusius derece anlamına gelen bir _single_ karakter olan “' ℃ '” da var. Unicode Consortium'a teşekkürler! –

cevap

8

Olası taşınabilir çözüm:

dönüştürme giriş unicode aktarın ve normal ifadelerde re.UNICODE bayrağı kullanın.

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
import re 


data = u'temp1:  +31.0°C (crit = +107.0°C)' 
temp_re = re.compile(ur'(temp1:)\s+(\+|-)(\d+\.\d+)°C\s+' 
        ur'\(crit\s+=\s+(\+|-)(\d+\.\d+)°C\).*', flags=re.UNICODE) 

print temp_re.findall(data) 

Çıktı

[(u'temp1:', u'+', u'31.0', u'+', u'107.0')] 

@netvope DÜZENLEME Allready soru için yorumlardaki bu dikkat çekti. giriş kodlaması hakkında J.F. Sebastian yorumlardan

Güncelleme

Notlar:

check_output() getiri bazen metin olabilir ikili veri (yani bu durumda bilinen bir karakter kodlamasını olmalı ve bunu dönüştürebilirsiniz Unicode'a). Neyse ord (u '°') == 176 bu yüzden ASCII kodlaması kullanılarak kodlanamaz.

Yani temelde * Eğer locale.getpreferredencoding() kullanarak sistem dilinden şifrelemeyi kullanmalıdır, unicode için giriş verileri deşifre etmek örn: verileriyle

data = subprocess.check_output(...).decode(locale.getpreferredencoding()) 

doğru kodlanmış:

elde edersiniz Bu durumda re.UNICODE olmadan aynı çıktı. Neden temelde


?Çünkü cp1251 ile Rus Win7 üzerinde olarak preferredencoding biz utf-8 çıkış var deşifre örneğin script.py için varsa:

#!/usr/bin/env python 
# -*- coding: utf8 -*- 

print u'temp1: +31.0°C (crit = +107.0°C)'.encode('utf-8') 

Ve çıkış var ayrıştırmak için çiş gerek:

subprocess.check_output(['python', 
         'script.py']).decode(locale.getpreferredencoding()) 

yanlış sonuçlar üretecektir: 'В°' yerine °.

Bazı durumlarda giriş verilerinin kodlamasını bilmeniz gerekir.

+0

Elbette, ama bu tür bir şey için tam bir çalışma örneği her zaman iyi bir fikirdir. Unicode'u düzgün bir şekilde kullanmak, tam imkanlar mevcut olduğunda bile birçok programcı için zordur :( –

+0

+1: "giriş verilerini unicode'a dönüştürmek" için. Btw, bu durumda 're.UNICODE' olmadan aynı çıkışı elde edersiniz. – jfs

+0

Bunun için teşekkürler.Onunla bir oyun yaşadım.Yüksekte "gerçek" kodda, veri aslında bir çağrının çıktısından "subprocess.check_output" çıktısından geliyor, bu da veriyi Unicode değil, ASCII olarak döndürüyor. Orada oldukça çalışır.Python3'e "her şey" Unicode olan H3'e geçmek daha mantıklı bir şey olabilir mi? – snim2

İlgili konular