2012-07-10 89 views
1

我在工作中遇到了一個問題,需要我在PostgreSQL數據庫中插入一些MASSIVE製表符分隔值文件(將8-15 GB的.txt文件考慮在內),但是我數據格式化的方式首先遇到了問題。基本上,我們獲得數據的方式(不幸的是我們無法以更好的格式獲取數據),出現一些反斜槓並導致返回/換行。從製表符分隔的值中刪除某些返回字符文件

所以,有幾行(數據行,tab-delim)被切分成多行,其中第n行的最後一個字符是\,並且第n + 1行的第一個字符是一個製表符。通常n行會被分成1-3行(例如,行n以「\」結尾,行n + 1和n + 2以製表符開頭並以「\」結尾,行n + 3開始帶有一個標籤)。

我需要編寫一個腳本,可以與這些巨大的文件(這將運行在具有192 GB的RAM的Linux服務器上運行)尋找以製表符開頭的行,然後刪除返回(和「 \「無論它存在於何處)並保存文本文件。

回顧一下,客戶的日誌記錄程序將原始行N拆分爲行n,n + 1,有時n + 2和n + 3(具體取決於行N中出現多少個\字符),我需要寫一個python腳本來重建原始的線N.

+0

發佈一個小樣本,其中包含任何敏感的編輯內容。預期的投入和產出是說明這種問題的好方法。 – MattH 2012-07-10 14:28:39

回答

0

這是基於@ user665637的很好的答案。

#!/usr/bin/python 

import re, sys 

pat_incomplete = re.compile(r'\\\s*$') 
pat_indented = re.compile(r'^\t') 

try: 
    _, fname_in, fname_out = sys.argv 
except ValueError: 
    print("Usage: python line_joiner.py <input_filename> <output_filename>") 
    sys.exit(1) 

with open(fname_in) as in_f, open(fname_out, "w") as out_f: 
    lines = iter(in_f) 
    try: 
     line = next(lines) 
     s = pat_incomplete.sub('', line) 
    except StopIteration: 
     print("Input file did not contain any data") 
     sys.exit(2) 

    for line in lines: 
     line = pat_incomplete.sub('', line) 
     if pat_indented.match(line): 
      s += pat_indented.sub('',line) 
     else: 
      out_f.write(s) 
      s = line 
    out_f.write(s) 

變化:

  • 使用 「原始字符串」 正則表達式,它們更容易閱讀。

  • 從命令行參數中獲取輸出文件名並寫入該文件。打印消息並退出,如果用戶提供的參數數量錯誤。當我們解壓sys.argv以獲得參數時,我們使用變量名稱_作爲我們不關心的部分。

  • 不去掉行結尾,所以輸出文件將具有與輸入文件相同的行尾。 (當加入線時,它當然會剝離線端以進行連接。)

  • 不會從輸入中濾除空行。這有點棘手,但通過迭代器並調用next(),它在啓動循環之前獲得第一個輸入行;因此s從有效值開始而不是None開始,我們不必每次測試它是否打印它。原始if lastLine:測試在被剝離的輸入行上不僅會保護None的初始值lastLine,而且還會過濾輸入中的所有空行。

  • 如果你必須在Python 3.0或Python 2中使用它。6,您不能有一個with聲明,它會執行兩個open()調用;但您可以將它變成兩個嵌套的with語句,每個語句都會執行一個open()

+0

非常感謝!你節省了我大量的時間。讓我知道,如果有什麼我可以爲你做的(慈善機構,你想捐贈什麼?等)! – user1514979 2012-07-10 19:20:02

+0

不客氣!如果你真的想要給EFF另一個小額捐款,但請不要覺得你必須這樣做。 – steveha 2012-07-10 19:20:59

1

不受任何替換 「\ n」 個序列:

In [20]: a="blabla\tblabla\tblabla\\\n\tblabla\tblabla" 

In [21]: print(a) 
blabla blabla blabla\ 
    blabla blabla 

In [22]: a=a.replace('\\\n', '') 

In [23]: print(a) 
blabla blabla blabla blabla blabla 

:)

+0

如承諾的那樣,給EFF 10美元: – user1514979 2012-07-10 17:06:33

+0

@ user1514979:如果答案有幫助,您應該注意或接受它。捐款很好,但不能代替這裏的習俗。 – 2012-07-10 18:13:48

+0

這不回答這個問題。他具有需要合併的特定格式的輸入行,輸入文件很大,因此需要逐行讀取。 – steveha 2012-07-10 18:22:24

2
#!/usr/bin/python 

import re,sys 

lastLine = None 
incomplete = re.compile("\\\\+$") 
indented = re.compile("^\\t") 

for line in open(sys.argv[1]): 
    line = line.rstrip() 
    line = incomplete.sub("", line) 
    if indented.match(line): 
     lastLine += indented.sub("",line) 
    else: 
     if lastLine: 
      print lastLine 
      lastLine = None 
     lastLine = line 

print lastLine 

基本上,我忽略了\在自選項卡結束在下一行告訴你,無論如何這是一個延續。

+0

非常感謝!如承諾的那樣,給EFF 10美元(不太確定如何在評論中直接發佈圖片,所以這裏有一個鏈接): [link](http://i.imgur.com/V2chc.png) 現在,這段代碼好像可以工作,但是我怎樣才能讓它讀取文本文件並保存一個正確的文本文件。換句話說,我會想象使用命令: – user1514979 2012-07-10 17:08:39

+0

<繼續...>'python cleanData.py uglyData.tsv'然後將清理過的數據保存在名爲uglyData-CLEAN.tsv的文本文件中行呢? – user1514979 2012-07-10 17:14:51

+0

+1爲一個很好的答案。我對它做了一些調整併發布了我自己的版本,但是完全贊同源代碼。 – steveha 2012-07-10 19:18:20

相關問題