Bash:使用引号,逗号和换行符解析CSV

Jac*_*lyk 7 csv bash awk cut gawk

假设我有以下csv文件:

 id,message,time
 123,"Sorry, This message
 has commas and newlines",2016-03-28T20:26:39
 456,"It makes the problem non-trivial",2016-03-28T20:26:41
Run Code Online (Sandbox Code Playgroud)

我想编写一个只返回时间列的bash命令.即

time
2016-03-28T20:26:39
2016-03-28T20:26:41
Run Code Online (Sandbox Code Playgroud)

最直接的方法是什么?您可以假设标准unix工具的可用性,例如awk,gawk,cut,grep等.

注意存在的"逃逸",以及用于进行琐碎尝试的换行符

cut -d , -f 3 file.csv
Run Code Online (Sandbox Code Playgroud)

徒劳的.

hek*_*mgl 7

正如chepner所说,我们鼓励您使用能够解析csv的编程语言.

这是python中的一个例子:

import csv

with open('a.csv', 'rb') as csvfile:
    reader = csv.reader(csvfile, quotechar='"')
    for row in reader:
        print(row[-1]) # row[-1] gives the last column
Run Code Online (Sandbox Code Playgroud)


Sri*_*niV 7

正如这里所说

gawk -v RS='"' 'NR % 2 == 0 { gsub(/\n/, "") } { printf("%s%s", $0, RT) }' file.csv \
 | awk -F, '{print $NF}'
Run Code Online (Sandbox Code Playgroud)

要专门处理双引号字符串中的换行符并保留它们之外的换行符,请使用GNU awk(for RT):

gawk -v RS='"' 'NR % 2 == 0 { gsub(/\n/, "") } { printf("%s%s", $0, RT) }' file
Run Code Online (Sandbox Code Playgroud)

这是通过沿字符分割文件"并删除每个其他块中的换行符来实现的。

输出

time
2016-03-28T20:26:39
2016-03-28T20:26:41
Run Code Online (Sandbox Code Playgroud)

然后使用awk分割列并显示最后一列


Aar*_*lla 6

CSV 是一种需要适当解析器的格式(即不能单独使用正则表达式进行解析)。如果安装了Python,请使用该csv模块而不是普通的 BASH。

如果没有,请考虑csvkit,它有很多强大的工具可以从命令行处理 CSV 文件。

也可以看看: