2013-12-12 33 views
0

我有一堆帶有表格數據的文本文件。它看起來像這樣:用python讀表格數據

1. BRISTOL CITY    42 16 4 1 43 13 8 7 6 23 27 59 
2. Plymouth Argyle   42 18 3 0 47 6 5 4 12 14 23 53 
3. Swansea City    42 13 6 2 46 14 9 3 9 32 31 53 
4. Brighton & Hove Albion 42 15 3 3 39 13 5 8 8 13 21 51 
5. Luton Town    42 14 4 3 47 18 7 3 11 21 31 49 
6. Millwall     42 9 10 2 27 13 5 8 8 18 27 46 
7. Portsmouth    42 10 5 6 34 20 9 3 9 24 32 46 
8. Northampton    42 13 6 2 40 17 4 5 12 14 27 45 
9. Swindon Town    42 14 4 3 41 17 3 7 11 21 39 45 
10. Watford     42 10 6 5 35 23 7 4 10 22 31 44 
11. Queen's Park Rangers  42 10 4 7 34 24 6 6 9 20 25 42 
12. Charlton Athletic  42 11 6 4 33 14 3 8 10 22 37 42 
13. Bristol Rovers   42 7 9 5 25 19 6 7 8 10 17 42 
14. Brentford    42 9 4 8 27 23 4 8 9 14 28 38 
15. Southend United   42 10 6 5 35 18 2 7 12 14 36 37 
16. Gillingham    42 13 4 4 38 18 2 3 16 13 41 37 
17. Merthyr Town    42 10 4 7 27 17 1 10 10 12 31 36 
18. Norwich City    42 8 7 6 29 26 5 3 13 22 45 36 
19. Reading     42 9 8 4 24 15 1 6 14 12 40 34 
20. Exeter City    42 10 4 7 27 18 3 3 15 20 66 33 

這是非常有規律的,但沒有標準分離器和列寬並不表(即使在同一文件)表標準。 (單獨的空間不是足夠的分隔符,因爲許多名稱都包含空格,並且在某些地方,列僅由一個空格分隔)。

我想將其解析爲Python對象,但它不是很清楚什麼是最好的方法是。有沒有辦法使用CSV模塊來解析它?我需要使用正則表達式嗎?有人寫了一個很棒的python庫來解析表格文本文件嗎?

+1

會發生什麼,當您嘗試使用'csv'模塊?它不工作? – monkut

+0

是'\ t'的分隔符嗎? – ciphor

+0

您可以使用正則表達式來匹配每行的每個元素。 –

回答

1

做了一個工作正則表達式。 Look it up here for explanation/modifying.

該行的名稱(如Accrington)用[\D]+?提取。這意味着「採取儘可能多的非數字,因爲你需要適應該行」。 (+? - 非貪婪)這樣你就可以得到字母和(最小的)空白,這將是你的線路名稱...

import re 
pattern = re.compile(r"^(\d+.)\s*([\D]+?)" + r"\s+(\d+)"*12 + r"\s*$") 

測試

match = pattern.match("7. Accrington    22 5 3 3 26 17 1 5 5 22 31 20") 
print match.groups() 
Out[133]: 
('7.', 
'Accrington', 
'22', 
'5', 
'3', 
'3', 
'26', 
'17', 
'1', 
'5', 
'5', 
'22', 
'31', 
'20') 

match2 = pattern.match("91. Accrington Bay    22 5 3 3 26 17 1 5 5 22 31 20") 
print match2 
Out[134]: 
('91.', 
'Accrington Bay', 
'22', 
'5', 
'3', 
'3', 
'26', 
'17', 
'1', 
'5', 
'5', 
'22', 
'31', 
'20') 
+0

是的,這個工作,並且比我正在工作的正則表達式更好,謝謝!我希望有一個非正則的方法來做到這一點,但我可能會使用它。 – futuraprime

0

最簡單的解決方案是使用正則表達式。

您可以使用split()方法(包括Python的re模塊除外)在每個連續空白序列處拆分數據。

import re 

data = '7. Accrington    22 5 3 3 26 17 1 5 5 22 31 20' 
for line in re.split('\n+', data): 
    print(re.split('\s+', line)) 

這將打印以下:

['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '20'] 

注意的是,上述實施例還處理數據的多個線(假設這樣的線由連續的換行符隔開)。

+1

如果OP只是分割連續的空白,那麼就不需要're':只要'line.split()'就可以做到。但是OP需要至少做更多的工作,因爲名稱部分可能包含多個單詞。但是,如果最終的術語都是數字,他可以重新組合。 – DSM

+0

好點;我修改了我的示例,僅在兩個或多個空白字符的序列處進行分割。 – caleb531

+0

這樣做也不行:OP警告說有時候列只能被一個空格分開。 :^) – DSM

0

skipinitialspace就是你需要使用此模塊的csv模塊。

$ cat <<EOF> /tmp/sample.csv 
> 7. Accrington    22 5 3 3 26 17 1 5 5 22 31 20 
> 7. Accrington    22 5 3 3 26 17 1 5 5 22 31 20 
> 8. Accrington    22 5 3 3 26 17 1 5 5 22 31 22 
> 7. Accrington    22 5 3 3 26 17 1 5 5 22 31 21 
> EOF 
$ python 
Python 2.7.5 (default, Aug 25 2013, 00:04:04) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import csv 
>>> reader = csv.reader(open('/tmp/sample.csv'), skipinitialspace=True, quoting=csv.QUOTE_NONE, delimiter=' ') 
>>> for row in reader: 
...  print row 
... 
['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '20'] 
['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '20'] 
['8.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '22'] 
['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '21'] 

不要忘記你可以解壓結果的每一行,像這樣:

>>> for pk, name, a, b, c, d, e, f, g, h, i, j, k, l in reader: 
+0

根據OP,許多名稱(我假設這意味着第二個領域)包含空格。 –