簡體   English   中英

使用awk或sed打印用雙引號引起來的CSV文件列

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM