2013-02-16 25 views
5

birçok programlama dillerinin standart kütüphane metin girişi akışlarından dizeleri, sayı veya diğer nesneleri ayıklamak için bir "tarayıcı API" içerir. (Örneğin, Java, Scanner sınıfını içerir, C++, istream içerir ve C, scanf içerir).Python Akış Ekstraksiyon

Python bu eşdeğer nedir?

Python io.IOBase devralan bir akış arayüzü, yani sınıfları vardır. Bununla birlikte, Python TextIOBase akış arabirimi sadece hat yönelimli giriş için olanaklar sağlar. reading the documentation ve searching on Google10'dan sonra, standart Python modüllerinde, örneğin bir metin akışından tamsayı ayıklamam veya bir boşluk olarak bir sonraki boşlukla ayrılmış sözcüğü ayıklamamı sağlayan bir şey bulamıyorum. Bunu yapmak için herhangi bir standart tesis var mı?

+0

Giriş çok kirli/keyfi ise, ben 're' modülünü kullanma eğilimindedir; Eğer giriş yapılandırılmışsa, basitparse gibi bir ayrıştırıcı kütüphanesini tercih ederim (EBNL'nin normal ifadelerden daha kolay korunması). –

+1

Aklınızda bir kullanım durumunuz varsa, genel bir sorgulama yapmak yerine sorunuzu güncellemek daha verimli olabilir. –

+0

Diğer öneriler için http://stackoverflow.com/questions/2175080/sscanf-in-python adresine bakın. –

cevap

3

hiçbir fscanf eşdeğer veya Java en Scanner yoktur. En basit çözüm, kullanıcının alan ayrılmış giriş yerine yeni satır ayrımlı girişi kullanmasını gerektirmesidir, daha sonra satır satır okuyabilir ve çizgileri doğru türe dönüştürebilirsiniz.

Kullanıcı sonra muhtemelen kullanıcı girişi için bir ayrıştırıcı oluşturmalıdır daha yapısal girdi sağlamak istiyorum. Python için bazı güzel ayrıştırma kütüphaneleri vardır, örneğin pyparsing. Ayrıca, son güncelleştirme 2008 olmasına rağmen modülü de vardır.

Dış bağımlılıklara sahip olmak istemiyorsanız, giriş dizileriyle eşleştirmek için normal ifadeleri kullanabilirsiniz. Düzenli ifadeler dizeler üzerinde çalışmayı gerektirir, ancak bu sınırlama okumasını kolayca yığınlarda üstesinden gelebilirsiniz. Örneğin böyle bir şey de çoğu zaman çalışması gerekir:

import re 


FORMATS_TYPES = { 
    'd': int, 
    'f': float, 
    's': str, 
} 


FORMATS_REGEXES = {  
    'd': re.compile(r'(?:\s|\b)*([+-]?\d+)(?:\s|\b)*'), 
    'f': re.compile(r'(?:\s|\b)*([+-]?\d+\.?\d*)(?:\s|\b)*'), 
    's': re.compile(r'\b(\w+)\b'), 
} 


FORMAT_FIELD_REGEX = re.compile(r'%(s|d|f)') 


def scan_input(format_string, stream, max_size=float('+inf'), chunk_size=1024): 
    """Scan an input stream and retrieve formatted input.""" 

    chunk = '' 
    format_fields = format_string.split()[::-1] 
    while format_fields: 
     fields = FORMAT_FIELD_REGEX.findall(format_fields.pop()) 
     if not chunk: 
      chunk = _get_chunk(stream, chunk_size) 

     for field in fields: 
      field_regex = FORMATS_REGEXES[field] 
      match = field_regex.search(chunk) 
      length_before = len(chunk) 
      while match is None or match.end() >= len(chunk): 
       chunk += _get_chunk(stream, chunk_size) 
       if not chunk or length_before == len(chunk): 
        if match is None: 
         raise ValueError('Missing fields.') 
        break 
      text = match.group(1) 
      yield FORMATS_TYPES[field](text) 
      chunk = chunk[match.end():] 



def _get_chunk(stream, chunk_size): 
    try: 
     return stream.read(chunk_size) 
    except EOFError: 
     return '' 

Örnek kullanım:

>>> s = StringIO('1234 Hello World -13.48 -678 12.45') 
>>> for data in scan_input('%d %s %s %f %d %f', s): print repr(data) 
...                        
1234                       
'Hello' 
'World' 
-13.48 
-678 
12.45 

Muhtemelen bu genişletmek ve düzgün test gerekecek ancak bazı fikir edinebilirsiniz .

1

(aynı bildiğim kadarıyla) doğrudan eşdeğer yoktur. Ancak, normal ifadelerle aynı şeyi hemen hemen yapabilirsiniz (bkz. re modülü). Örneğin

:

# matching first integer (space delimited) 
re.match(r'\b(\d+)\b',string) 

# matching first space delimited word 
re.match(r'\b(\w+)\b',string) 

# matching a word followed by an integer (space delimited) 
re.match(r'\b(\w+)\s+(\d+)\b',string) 

Her zamanki C tarzı tarayıcı arayüzüne biraz daha çalışma gerektirir, ama aynı zamanda çok esnek ve güçlüdür. Akış G/Ç'sini kendiniz işlemek zorunda kalacaksınız.