[英]How to convert CSV with Double Quotes into OpenCSV using SED or AWK?
[英]Using awk or sed to print column of CSV file enclosed in double quotes
我正在處理以下csv文件,以逗號分隔,每個單元格都用雙引號引起來,但是其中一些包含雙引號和/或雙引號內的逗號。 實際文件包含大約300列和200,000行。
"Column1","Column2","Column3","Column4","Column5","Column6","Column7"
"abc","abc","this, but with "comma" and a quote","18"" inch TV","abc","abc","abc"
"cde","cde","cde","some other, "cde" here","cde","cde","cde"
我需要刪除一些除非列,然后合並最后幾列,而不是在它們之間使用","
, </br>
需要</br>
。 並將第二列移到末尾。 單元格中的所有內容都應相同,並使用雙引號和逗號作為原始文件。 以下是我需要的輸出示例。
"Column1","Column4","Column5","Column2"
"abc","18"" inch TV","abc</br>abc</br>abc","abc"
"cde","some other, "cde" here","cde</br>cde</br>cde","cde"
在此示例中,我想刪除column3並合並5、6、7。
下面是我嘗試使用的代碼,但是它正在讀取雙引號和/或逗號,該行的結尾與我期望的不同。
awk -vFPAT='([^,]*)|("[^"]+")' -vOFS=, '{print $1,$4,$5"</br>"$6"</br>"$7",$2}' inputfile.csv
sed -i 's@"</br>"@</br>@g' inputfile.csv
sed用於刪除單元格的開始和結束雙引號。
我現在正在獲取的輸出文件,如果上一個字段包含雙引號,它將認為這是單元格的開始,因此以下值通常被上推至一列。
我使用的其他代碼將每個逗號都視為一個單元格的開頭,因此它也不起作用。
awk -F',' 'BEGIN{OFS=",";} {print $1,$4,$5"</br>"$6"</br>"$7",$2}' inputfile.csv
sed -i 's@"</br>"@</br>@g' inputfile.csv
任何幫助是極大的贊賞。 謝謝!
CSV是一種寬松格式。 格式可能會有細微的變化。 您的特定格式可能會也可能無法通過正則語法/正則表達式表達。 (有關此問題的討論,請參閱此問題 。)即使您的特定格式可以用正則表達式表示,從現有庫中提取解析器也會更容易。
它不是您可能想要或需要的bash / awk / sed解決方案,但是Python具有用於解析CSV文件的csv
模塊。 有許多選項可以調整格式。 嘗試這樣的事情:
#!/usr/bin/python
import csv
with open('infile.csv', 'r') as infile, open('outfile.csv', 'wb') as outfile:
inreader = csv.reader(infile)
outwriter = csv.writer(outfile, quoting=csv.QUOTE_ALL)
for row in inreader:
# Merge fields 5,6,7 (indexes 4,5,6) into one
row[4] = "</br>".join(row[4:7])
del row[5:7]
# Copy second field to the end
row.append(row[1])
# Remove second and third fields
del row[1:3]
# Write manipulated row
outwriter.writerow(row)
請注意,在Python中,索引以0開頭(例如, row[1]
是第二個字段)。 切片的第一個索引為包含索引,最后一個索引為排斥索引(僅row[1:3]
為row[1]
和row[2]
)。 您的格式似乎要求每個字段都quoting=csv.QUOTE_ALL
引號,因此quoting=csv.QUOTE_ALL
。 “ 方言和格式參數”中有更多選項。
上面的代碼產生以下輸出:
"Column1","Column4","Column5</br>Column6</br>Column7","Column2"
"abc","18"" inch TV","abc</br>abc</br>abc","abc"
"cde","some other, cde"" here""","cde</br>cde</br>cde","cde"
這有兩個問題:
它不會對第一行進行不同的處理,因此第5、6和7列的標題與其他行一樣合並。
您輸入的CSV包含"some other, "cde" here"
(第三行,第四列),並在cde
周圍帶有未轉義的引號。 第二行還有另一種情況,但是由於它在第3列中而被刪除了。結果包含不正確的引號。
如果這些引號正確轉義,則示例輸入CSV文件將變為
infile.csv (引號) :
"Column1","Column2","Column3","Column4","Column5","Column6","Column7"
"abc","abc","this, but with ""comma"" and a quote","18"" inch TV","abc","abc","abc"
"cde","cde","cde","some other, ""cde"" here","cde","cde","cde"
現在考慮修改后的Python腳本,該腳本不會合並第一行中的列:
#!/usr/bin/python
import csv
with open('infile.csv', 'r') as infile, open('outfile.csv', 'wb') as outfile:
inreader = csv.reader(infile)
outwriter = csv.writer(outfile, quoting=csv.QUOTE_ALL)
first_row = True
for row in inreader:
if first_row:
first_row = False
else:
# Merge fields 5,6,7 (indexes 4,5,6) into one
row[4] = "</br>".join(row[4:7])
del row[5:7]
# Copy second field (index 1) to the end
row.append(row[1])
# Remove second and third fields
del row[1:3]
# Write manipulated row
outwriter.writerow(row)
輸出outfile.csv是
"Column1","Column4","Column5","Column2"
"abc","18"" inch TV","abc</br>abc</br>abc","abc"
"cde","some other, ""cde"" here","cde</br>cde</br>cde","cde"
這是您的示例輸出,但帶有正確轉義的"some other, ""cde"" here"
。
這可能不是您想要的,不是sed或awk解決方案,但我希望它仍然有用。 處理更復雜的格式可能證明更復雜的工具是合理的。 使用現有的庫也消除了一些出錯的機會。
這可能是問題的過分簡化,但是對您的測試數據來說這對我有用:
cat /tmp/inputfile.csv | sed 's@\"\,\"@|@g' | sed 's@"</br>"@</br>@g' | awk 'BEGIN {FS="|"} {print $1 "," $4 "," $5 "</br>" $6 "</br>" $7 "," $2}'
請不要因為我在Mac上,否則可能就是為什么必須在AWK腳本中用引號將逗號引起來。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.