2013-03-08 12 views
6

Ben piton CSV okuyucu kullanmak istiyorum ama içinde tırnak bırakmak istiyorum İstediğim geçerli:.Python'un csv okuyucusu alıntıları bırakabilir mi?

>>> s = '"simple|split"|test' 
>>> reader = csv.reader([s], delimiter='|', skipinitialspace=True) 
>>> reader.next() 
['"simple|split"', 'test'] 

Ama aslında alıyorum: Benim durumumda

['simple|split', 'test'] 

ben alıntı istiyorum hala aktarılan aktarılacak dize.

CSV okuyucunun amaçlanan şekilde çalıştığını biliyorum ve kullanım durumum bunun bir kötüye kullanımı, ancak bunu benim isteğime göre bükmenin bir yolu var mı? Yoksa kendi dizgim çözümleyicimi mi yazmalıyım?

+0

Sen olacak kendi ayrıştırıcınızı yazmanız gerekir. Tırnaklar, aksi halde tek bir sütun olarak görülmeyen veriden kaçmanın bir yoludur ve dolayısıyla çıktının bir parçası olarak kabul edilmez. –

+1

Verilerin ne kadar karmaşık olduğuna bağlı olarak, 'filtre (Yok, re.split (r' (". *?") | \ | ', S)) 'gibi bir şeyi aldatıp kullanabilirsiniz. 'pyparsing' –

+0

'ya Merhaba, Martino ve Jon'un söylediklerini geliştirdiğim bir cevabı yayınladım. Neden bir regex kullanmayı düşünmediğini söyler misin? – eyquem

cevap

3

Sen Modules/_csv.c bulunan özellikle parse_process_char yılında şeylerin C tarafında ise ayrıştırma ve tırnak yedekler modülün bir parçası olarak, kendi ayrıştırıcı yazmak zorunda gidiyoruz:

else if (c == dialect->quotechar && 
      dialect->quoting != QUOTE_NONE) { 
     if (dialect->doublequote) { 
      /* doublequote; " represented by "" */ 
      self->state = QUOTE_IN_QUOTED_FIELD; 
     } 
     else { 
      /* end of quote part of field */ 
      self->state = IN_FIELD; 
     } 
    } 
    else { 
     /* normal character - save in field */ 
     if (parse_add_char(self, c) < 0) 
      return -1; 
    } 

O "alıntı bölümünün sonu bölümü" bölümü, çift fiyat teklifinizi kesen bölümdür. Öte yandan, bu else koşulunu kesebilir ve python kaynak kodunu yeniden oluşturabilirsiniz. Ancak bu, dürüst olmak için sürdürülebilecek her şey değildir.

Düzenleme. Üzgünüm self->state = IN_FIELD yüzden de alıntı ekler önceki son else den biraz eklemek

+0

Bu oldukça kesin bir cevap! Teşekkür ederim. –

+0

@HamishDowner Aslında PyPy (Python in Python) modülünü kullanma ve onu bir projeye bırakılabilen özel bir tane oluşturmak için değiştirmeyi düşündüm. Bununla biraz oyuncak yapıyorum ve işe yarayabiliyor mu diye görüyorum, böylece herhangi bir tekerleği yeniden icat etmek zorunda değilsiniz. – cwgem

+1

@HamishDowner Evet Bir şans verdim ama PyPy'nin csv modül kodu, pythonda bile olsa, hala etrafa dağılmış çok miktarda püskürme ithalatına sahip. Maalesef biraz fazla çaba sarfederim. Nasıl idare edileceğine dair bazı fikirlere ihtiyacınız varsa, [csv reader kodunu] (https://bitbucket.org/pypy/pypy/src/5a61eff6b57fa1bfa95bd0d04e4a9421dadada987ce/pypy/module/_csv/interp_reader.py) 'e bakmak isteyebilirsiniz. çözümleyici çalışır. – cwgem

2

Eğer elde etmek için çalışıyoruz ne net bir görüş varsa ben anlamıyorum geliyordu.
diyorsunuz "Biliyorum (...) kullanım durumum bir kötüye kullanım".
Ancak istismar, kullanım olasılığının bulunduğunu ima eder.
Bununla birlikte, sizin için, "tanımladığınız" ın imkansız olduğu bir kullanım mümkün değildir, çünkü bir CSV ayrıştırıcısına geçirilen, geçerli bir CSV biçiminde olmalıdır ve sizinki değil.

Bir CSV geçerli dizesinde, karakterlerin çoğu bilgi olur ve bazı karakterler bilgileri ayıklamak için dizeyi yorumlamak için gerekli olan meta bilgilerdir.
Tanımladığınız şey, " karakterlerinin tamamen bilgi kategorisinde ve meta bilgi kategorisinde olmasını istemektir. Sol eliyle sol elini yakalamak isteyen birine benziyor .....

Bu sorun, dizinizde bir CSV dosyasının okunmasından gelen bir dize olmadığından oluşuyor. Yazılan bir dizedir.
CSV dosyasında bu şekilde yazılmamış olabileceğinden, böyle bir dizeyi bir CSV dosyasının okunmasından elde etmek imkansızdır. CSV dosyasına yazılır ise
, '"simple|split"|test'

  • veya #"simple#|split#"|test
    doublequote = False, escapechar = '#'

  • ile True doublequote seti, varsayılan ile

  • """simple|split"""|test

      yazılmış olabilir.

      Eğer, size sadece mevcut bir aracı kullanmak zorunda bir ayrıştırıcı yaratmak değil var anlatıldığı gibi bilgileri ayıklamak isterseniz:

      import re 
      
      reg = re.compile('".*?"|[^|]+') 
      
      print reg.findall('yoo|"simple|split"|test|end"pos|hu') 
      

      sonucu

      ['yoo', '"simple|split"', 'test', 'end"pos', 'hu'] 
      
  • İlgili konular