Bash 使用awk或sed打印包含在双引号中的CSV文件列

Bash 使用awk或sed打印包含在双引号中的CSV文件列,bash,csv,awk,sed,Bash,Csv,Awk,Sed,我正在处理一个csv文件,如下图所示,以逗号分隔,每个单元格都用双引号括起来,但其中一些包含双引号和/或双引号内的逗号。实际文件包含大约300列和200000行 "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"

我正在处理一个csv文件,如下图所示,以逗号分隔,每个单元格都用双引号括起来,但其中一些包含双引号和/或双引号内的逗号。实际文件包含大约300列和200000行

"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"
我需要删除一些列,并合并最后几列,而不是在它们之间添加
,“
,我需要

。并将第二列移到末尾。单元格中的任何内容都应相同,并使用双引号和逗号作为原始文件。下面是我需要的输出示例

"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"
“第1列”、“第4列”、“第5列”、“第2列”
“abc”、“18英寸电视”、“abc
abc
abc”、“abc” “cde”、“其他一些”、“这里的cde”、“cde
cde
cde”、“cde”
在本例中,我想删除第3列并合并第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
awk-vFPAT='([^,]*)|(“[^”]+”)-vOFS=,“{print$1,$4,$5”
“$6”
“$7”,$2}”inputfile.csv sed-i's@“
”@
@g'inputfile.csv
sed用于删除单元格的开头和结尾双引号

我现在得到的输出文件,如果前一个字段包含一个双引号,它会考虑这是一个单元格的开头,所以下面的值经常被推到一列。p>

我使用的其他代码将每个逗号视为单元格的开始,因此也不起作用。

awk -F',' 'BEGIN{OFS=",";} {print $1,$4,$5"</br>"$6"</br>"$7",$2}' inputfile.csv

sed -i 's@"</br>"@</br>@g' inputfile.csv
awk-F','BEGIN{OFS=“,”;}{print$1,$4,$5“
“$6”
“$7”,$2}”inputfile.csv sed-i's@“
”@
@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)
这有两个问题:

  • 它对第一行的处理没有任何不同,因此第5、6和7列的标题与其他行一样合并

  • 您的输入CSV包含
    “其他”,此处为“cde”
    (第三行,第四列),在
    cde
    的周围有未替换的引号。第二行有另一种情况,但由于它位于第3列,因此被删除。结果包含不正确的引号

如果这些引号正确转义,则示例输入CSV文件将变为

infle.csv(转义引号):

现在考虑这个修改的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)
!/usr/bin/python
导入csv
将open('infle.csv','r')作为infle,将open('outfile.csv','wb')作为outfile:
inreader=csv.reader(内嵌)
outwriter=csv.writer(outfile,quoting=csv.QUOTE_ALL)
第一行=真
对于inreader中的行:
如果第一行:
第一行=False
其他:
#将字段5,6,7(索引4,5,6)合并为一个
第[4]行=“
”。加入(第[4:7]行) 德尔罗[5:7] #将第二个字段(索引1)复制到末尾 行。追加(行[1]) #删除第二个和第三个字段 德尔罗[1:3] #写操作行 outwriter.writerow(行)
输出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"
“第1列”、“第4列”、“第5列”、“第2列”
“abc”、“18英寸电视”、“abc
abc
abc”、“abc” “cde”、“其他一些”、“cde”、“此处”、“cde
cde
cde”、“cde”
这是您的示例输出,但使用正确转义的
“some other”,“cde”here“


这可能不是您想要的,不是sed或awk解决方案,但我希望它仍然有用。处理更复杂的格式可能会证明更复杂的工具是正确的。使用现有库也会消除一些出错的机会。

CSV是一种松散的格式。格式可能会有细微的变化。您的参与ular格式可以用正则语法/正则表达式表达,也可以不用正则表达式表达。(有关讨论,请参阅。)即使您的特定格式可以用正则表达式表达,也可以从现有库中快速生成解析器

它不是您想要或需要的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)
这有两个问题:

  • 它对第一行的处理没有任何不同,因此第5、6和7列的标题与其他行一样合并

  • 您的输入CSV包含
    “其他”,此处为“cde”
    (第三行,第四列),在
    cde
    的周围有未替换的引号。第二行有另一种情况,但由于它位于第3列,因此被删除。结果包含不正确的引号

如果这些引号正确转义,则示例输入CSV文件将变为

infle.csv(转义引号):

现在考虑这个修改的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)
!/usr/bin/python
导入csv
将open('infle.csv','r')作为infle,将open('outfile.csv','wb')作为outfile:
inreader=csv.reader(内嵌)
outwriter=csv.writer(outfile,quoting=csv.QUOTE_ALL)
第一行=真
对于inreader中的行:
如果第一行:
第一行=False
其他:
#将字段5,6,7(索引4,5,6)合并为一个
第[4]行=“
”。加入(第[4:7]行) 德尔罗[5:7] #抄袭
cat /tmp/inputfile.csv | sed 's@\"\,\"@|@g' | sed 's@"</br>"@</br>@g' | awk 'BEGIN {FS="|"} {print $1 "," $4 "," $5 "</br>" $6 "</br>" $7 "," $2}'