2009-10-14 26 views
0

有時我需要解析字符串是CSV,但我有麻煩引用昏迷。如此代碼所示。我使用Python 2.4python csv help

import csv 
for row in csv.reader(['one",f",two,three']): 
    print row 

我得到4種元素[ '一' 「 'F」', '兩節', '三化'],但我想獲得這個[ '一個 「F」' ,'two','three']或3個元素,即使我嘗試使用quotechar =''''選項(這是根據文檔默認值)仍然相同,我怎麼能忽略引號中的昏迷?

編輯: 謝謝大家的答案很明顯,我誤會了我的CSV輸入,等年底我解析爲鍵值STRIG(NAME,DESCR ...)

這是輸入

名稱: 「2801個底盤」,DESCR: 「2801個機箱,硬件序列號:XXXXXXX,漢王修訂:6.0」,PID:CISCO2801,VID:V03,SN:XXXXXXXXX

+1

請提供一個真實的數據示例 - 它似乎是您的數據不是csv。 – nosklo 2009-10-14 13:52:09

回答

3

你可以得到csv模塊告訴你,只需將你想要的輸出送入寫入器

In [1]: import sys,csv 

In [2]: csv.writer(sys.stdout).writerow(['one", f"', 'two', 'three']) 
"one"", f""",two,three 

In [3]: csv.reader(['"one"", f""",two,three']).next() 
Out[3]: ['one", f"', 'two', 'three'] 
+0

當我嘗試這與我的實際輸入我沒有得到期望的輸出 這STRIG 名稱:「2801個底盤」,DESCR:「2801個機箱,硬件序列號:XXXXXXX,漢王修訂:6.0」, PID:CISCO2801,VID:V03,SN:xxxxxxxxx – Ib33X 2009-10-14 12:53:02

+2

因此,實際上您的數據不是CSV,而是某種字典格式?鍵值對的逗號分隔列表? – 2009-10-14 13:37:21

6

其實你得到的結果是正確的 - 你的CSV語法是錯誤的。

如果要引用CSV值中的逗號或其他字符,則必須使用圍繞整個值的引號,而不是其中的部分。如果一個值不是以引號字符開頭,那麼Python的CSV實現不會假定該值是被引用的。

所以,而是採用

one",f",two,three 

你應該使用

"one,f",two,three 
+0

不幸的是,我沒有控制輸入字符串 – Ib33X 2009-10-14 12:53:48

+0

然後,我擔心你不能使用'csv'模塊開箱即用,但必須編寫自己的數據讀取器。 – 2009-10-14 13:35:40

1

你輸入的字符串是不是真的CSV。相反,您的輸入包含每一行中的列名稱。如果您的輸入如下所示:

NAME: "2801 chassis", DESCR: "2801 chassis, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 
NAME: "2802 wroomer", DESCR: "2802 wroomer, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 
NAME: "2803 foobars", DESCR: "2803 foobars, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 

您可以做的最簡單的操作可能是首先在整個文件中過濾掉列名。這會給你一個你可以解析的CSV文件。但是,假定每行都有相同順序的相同列。

但是,如果數據不一致,您可能需要根據名稱進行解析。也許它看起來像這樣:

NAME: "2801 chassis", PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx, DESCR: "2801 chassis, Hw Serial#: xxxxxxx, Hw Revision: 6.0" 
NAME: "2802 wroomer", DESCR: "2802 wroomer, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 
NAME: "2803 foobars", VID: V03 ,PID: CISCO2801 ,SN: xxxxxxxxx 

或者什麼。在這種情況下,我會通過查找第一個':'來解析每一行,從中分出列頭,然後解析該值(包括查找引號),然後繼續行的其餘部分。像這樣(完全未經測試的代碼):

def parseline(line): 
    result = {} 
    while ':' in line: 
     column, rest = line.split(':',1) 
     column = column.strip() 
     rest = rest.strip() 
     if rest[0] in ('"', '"'): # It's quoted. 
      quotechar = rest[0] 
      end = rest.find(quotechar, 1) # Find the end of the quote 
      value = rest[1:end] 
      end = rest.find(',', end) # Find the next comma 
     else: #Not quoted, just find the next comma: 
      end = rest.find(',', 1) # Find the end of the value 
      value = rest[0:end] 
     result[column] = value 
     line = rest[end+1:] 
     line.strip() 
    return result 
+0

您的函數將失敗,因爲':'可以是(引用的)值的一部分(參見DESCR)。在這裏使用正則表達式可能更容易! – 2009-10-14 15:55:08

+0

它不會因此而失敗,因爲它將單獨處理報價值。它從來不會看到引用的值爲: – 2009-10-14 17:33:38

+0

但它會失敗,因爲我忘了分割中的「,1」,在一個地方有[0,結束]而不是[0:結束],並返回值而不是結果。有了這三個改變它的作品。對於我甚至沒有嘗試運行的代碼來說都很不錯。 :) – 2009-10-14 17:38:53