我正在撰寫一個將 csv 合并為一個的腳本,然后查找特定格式的替換并要求用戶更正不匹配的那些。
import glob
import re
import csv
read_files = glob.glob("*.txt")
final_file = 'TABS3.ASC'
strformat1 = re.compile(r'\d{3}\.\d{5}')
#combine all files into one
with open(final_file, "wb") as outfile:
for f in read_files:
with open(f, "rb") as infile:
outfile.write(infile.read())
#read new file and check for matching string
with open(final_file, newline='') as fin:
check = list(csv.reader(fin))
for row in check:
if strformat1.match(row[0]):
pass
else:
show = print (row[0])
find = row[0]
replace = input ('How do you want to change: ')
check = ''.join(str(i) for i in check) \
.replace(str(find), str(replace))
with open(final_file, "w") as final:
final.write(check)
輸出不是正確的 csv 格式
['710.00501', '79', '1', 'L140', 'A110', '10/10/2022', '0.60', '', '', ""]['774.00006', '79', '1', 'L160', 'A103', '10/10/2022', '0.50', '', '', '']['714.00150', '79', '1', 'L140', 'A110', '10/10/2022', '4.00', '', '', '']
它應該是
"710.00501", "79", "1", "L140", "A110", "10/10/2022", "0.60", "", "", ""
"774.00006", "79", "1", "L160", "A103", "10/10/2022", "0.50", "", "", ""
"714.00150", "79", "1", "L140", "A110", "10/10/2022", "4.00", "", "", ""
uj5u.com熱心網友回復:
這個問題有很多不同的部分,你做了一個很好的嘗試:)
我建議將問題分解為三個不同的步驟和代碼塊:
- 以 CSV 格式讀取所有 txt 檔案,并將每組行添加到所有行的串列中。
- 迭代所有行并修改它以滿足您的需要。
- 最后,將所有行寫成 CSV。
它讓我能夠列印出資料并可視化剛剛發生的事情;它還使代碼縮進更少,更易于閱讀。
我根據您帖子中的資料模擬了三個非常小的輸入 TXT 檔案:
input1.txt
==========
710.00501,79,1,L140,A110,10/10/2022,0.60,,,
999.44,22,2,Z333,Y111,10/10/2022,0.66,,,
input2.txt
==========
774.00006,79,1,L160,A103,10/10/2022,0.50,,,
input3.txt
==========
714.00150,79,1,L140,A110,10/10/2022,4.00,,,
我還添加了一條與您的正則運算式不匹配的行,以在步驟 2 中練習代碼。
獲取所有行
我說“作為 CSV”是因為我看到您將檔案作為文本打開以收集所有行;也可以作為文字寫一行出來。這可能有效,但如果檔案沒有正確的最終換行符,那么您最終將合并當前檔案的最后一行和下一個檔案的第一行,例如:
999.44,22,2,Z333,Y111,10/10/2022,0.66,,,774.00006,79,1,L160,A103,10/10/2022,0.50,,,
在類似 CSV 的檔案上使用 csv 讀取器/寫入器總是更安全:它們將看到并尊重不同的資料行,而不僅僅是文本行。
all_rows = []
for fname in glob.glob("input*.txt"):
with open(fname, newline="") as f:
reader = csv.reader(f)
all_rows.extend(list(reader))
pprint.pprint(all_rows)
csv 檔案建議在所有讀寫實體中使用 newline="" 。
運行它,我們可以看到所有行:
[['710.00501', '79', '1', 'L140', 'A110', '10/10/2022', '0.60', '', '', ''],
[ '999.44', '22', '2', 'Z333', 'Y111', '10/10/2022', '0.66', '', '', ''],
['774.00006', '79', '1', 'L160', 'A103', '10/10/2022', '0.50', '', '', ''],
['714.00150', '79', '1', 'L140', 'A110', '10/10/2022', '4.00', '', '', '']]
這個列印輸出還幫助我們想象 csv 閱讀器將一行視為字串串列;all_rows 是字串串列的串列。
接下來,處理像“999.44”這樣的資料。
有選擇地修改行
我不確定您要使用該 join() 陳述句和替換變數做什么。以下代碼顯示了如何僅更改與您的正則運算式不匹配的行的第一列。
我喜歡檢查一行是否匹配某個條件,這意味著我應該忽略它,然后使用 continue 關鍵字跳轉到下一行;它消除了一定程度的縮進并避免了 else 陳述句,我通常認為這更可取:
num_re = re.compile(r"\d{3}\.\d{5}")
for row in all_rows:
some_num = row[0]
if num_re.match(some_num):
continue
change = input(f"\n'{some_num}' doesn't match, change it to: ")
row[0] = change.strip()
print()
pprint.pprint(all_rows)
運行它,我可以將 '999.44' 更改為 '999.44009' (同樣,不確定這是否是您真正需要的):
'999.44' doesn't match, change it to: 999.44009
[['710.00501', '79', '1', 'L140', 'A110', '10/10/2022', '0.60', '', '', ''],
['999.44009', '22', '2', 'Z333', 'Y111', '10/10/2022', '0.66', '', '', ''],
['774.00006', '79', '1', 'L160', 'A103', '10/10/2022', '0.50', '', '', ''],
['714.00150', '79', '1', 'L140', 'A110', '10/10/2022', '4.00', '', '', '']]
如果您想為整行替換每一列中的一些資料,我會在每一列上使用傳統的 for 回圈:
for i, col in enumerate(row):
row[i] = col.replace("foo", "bar")
這很容易閱讀和糾正。
寫下所有行
我們已經能夠在每個步驟中可視化資料并確保其正確性。現在寫出來只是幾行:
with open("output.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(all_rows)
我的 output.csv 看起來像:
710.00501,79,1,L140,A110,10/10/2022,0.60,,,
999.44009,22,2,Z333,Y111,10/10/2022,0.66,,,
774.00006,79,1,L160,A103,10/10/2022,0.50,,,
714.00150,79,1,L140,A110,10/10/2022,4.00,,,
綜上所述,最后的想法
沒有所有除錯列印陳述句,解決問題看起來相當緊湊:
all_rows = []
for fname in glob.glob("input*.txt"):
with open(fname, newline="") as f:
reader = csv.reader(f)
all_rows.extend(list(reader))
num_re = re.compile(r"\d{3}\.\d{5}")
for row in all_rows:
some_num = row[0]
if num_re.match(some_num):
continue
change = input(f"\n'{some_num}' doesn't match, change it to: ")
row[0] = change.strip()
with open("output.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(all_rows)
我還看到您在嘗試中這樣做:
...
check = list(csv.reader(fin))
for row in check:
...
我們可以在閱讀器上使用 list() 函式來獲取所有行以供以后處理,就像我們對 all_rows 所做的那樣。如果我們只想遍歷每一行,一次一個(而不是將每一行保存在記憶體中),我們可以直接在閱讀器上使用 for 回圈:
reader = csv.reader(fin)
for row in reader:
...
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/515552.html
上一篇:如何過濾資料集中的大寫字母
