在shell脚本中按列拆分CSV,但不使用唯一分隔符
我有一个包含多行的CSV,其中一些行如下所示在shell脚本中按列拆分CSV,但不使用唯一分隔符,csv,awk,split,Csv,Awk,Split,我有一个包含多行的CSV,其中一些行如下所示 "ABC","Unfortunately, system has failed"," - Error in system" "DEF","Check the button labelled "WARNING"","Warning in system" "XYZ","Everythin
"ABC","Unfortunately, system has failed"," - Error in system"
"DEF","Check the button labelled "WARNING"","Warning in system"
"XYZ","Everything is okay","No errors"
我需要拆分这些行并提取列,例如
我为每一行运行一个循环,并将第二列提取为
awk -F , '{print $2}' $line
其中,$line
表示每一行。然而,我最终得到了不正确的值。例如,当尝试获取第一行第二列时,使用上面的命令会给我“不幸的是
而不是“不幸的是,系统出现故障”
我知道我的字符串中同时包含逗号和引号,这使得基于分隔符进行拆分变得更加困难。还有什么我可以尝试的吗?使用GNU awk和
FPAT
:
$ gawk '
BEGIN {
FPAT="([^,]*)|(\"[^\"]+\")"
}
{
print $2
}' file
输出:
"Unfortunately, system has failed"
"Check the button labelled "WARNING""
"Everything is okay"
它不是完整的CSV解析器,例如引号内的换行符未被处理,您需要自己处理它们(检查NF
并合并记录)。有关FPAT
的更多信息:
$ gawk '
BEGIN {
FPAT="([^,]*)|(\"[^\"]+\")"
}
{
print $2
}' file
如果要删除这些引用:
$ gawk '
BEGIN {
FPAT="([^,]+)|(\"[^\"]+\")"
}
{
for(i=1;i<=NF;i++) # loop all fields
gsub(/^"|"$/,"",$i) # remove quotes surrounding fields
print $2
}' file
如果要将输入数据放入3x3表格中 您可以使用
awk
:
awk -v FS=',[^ ]' -v OFS="|" '{print $1, $2, $3}' file
ABC"|Unfortunately, system has failed"| - Error in system"
"DEF"|Check the button labelled "WARNING""|Warning in system"
"XYZ"|Everything is okay"|No errors"
守则:
- 为什么要设置
?系统中的逗号不是分隔符FS=',[^]'
“检查标记为“WARNING”的按钮”
(是的,它很难看,但也很难看;它来自Microsoft。)在每一行上分别运行Awk效率低下,而且很难看。只需在整个文件上运行它;这就是它的构建目的(而shell在将输入拆分为行方面做得更糟)另外,@tripleee是的,我希望输入有转义双引号。不幸的是,输入是从不同的应用程序发送的,我们无法控制它们发送的格式。如果您没有GNU Awk,您可以使用sed
来修饰每一行(即用其他分隔符替换,“
)然后使用awk
解析第二个字段,并用串联方式恢复包含的引号,例如sed's/“,“/~/g'file.csv”| awk-F~'{print'\'$2'\'}'
——使用'~'
作为修饰。通过替换整个模式“\,”“
带有”~'
——您知道要替换哪个:)
您是如何获得此输出的?我尝试了您建议的同一个命令,得到的输出是系统是
,那么您可能没有GNU Awk。@CluelessProgrammer您的Awk--version
报告是什么?如果它没有报告GNU Awk——那么FPAT
很可能不受支持。Awk版本20070501
看起来您有一台Mac电脑,但没有安装GNU Awk。@JamesBrown-您的脚本现在可以完美地工作了。非常感谢你。必须阅读更多关于FPAT
和gawk
的内容。这些天我只使用了awk
命令,但不是100%健壮,但我喜欢您选择的分隔符