我有一个 CSV,它看起来像
details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,"{1,2,3}",{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,"{4,5,6,7,8,9}",{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{1,9}","{NORMAL,BOOKING}",1,2,
这里 15 列为空,12 列在为单个值时没有引号({预订}) 并在具有多个值时加引号(“{预订,正常}”)。
由此我想删除 11 列,它是一个 int 数组并且没有固定大小。所以输出看起来像
mod_details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,
所以我尝试:
sed 's/,"{.*}"//' details.csv > mod_details.csv
但问题是我得到的输出为
mod_details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,1,2,
它还删除了第 12 列值,该值具有多个值,因为它也有引号。如有任何帮助,我们将不胜感激。提前致谢。
答案1
事实上,这并不是特别困难。您只需要使用比以下更具体的模式{.*}
:
sed 's/"{\([0-9],\)\+[0-9]}",//' details.csv
答案2
作为寻找答案的一步,您可能会发现以下 shell 函数很有帮助。我编写它是为了在命令行上以漂亮的“漂亮”布局查看 CSV。
注意它删除带引号的逗号和带引号的换行符(以及带引号的双引号),这可能不是您想要的,但对于快速查看并使列正确排列很有用。
excel() {
sed -E -e ':t' -e '/^[^"]*("[^"]*"[^"]*)*$/!{N;s/\n//;bt' -e'}' "$@" |
awk -F\" -v OFS= 'NF>1 {for (i=2;i<=NF;i+=2) gsub(/,/, "", $i)} 1' |
sed 's/,/,"/g' | column -ts, | tr -d '"' | less -S
}
答案3
使用csvkit
:
$ csvcut -C 11 details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,
答案4
将每一行拆分为数组"
作为分隔符是一种更简单的方法。然后,您的 int 数组将成为数组的元素 1,我们可以将其设置为空字符串,下一个(元素 2)将在其末尾附加额外的逗号,因此我们可以提取该起始的子字符串从第二个字符开始。现在,我们需要以{NORMAL,BOOKING}
某种方式处理将双引号返回到该部分。使用分割线"
作为分隔符,这也得到了处理,因为该行将具有字段 3。如果是其他行,则不再有引号,因此我们的项目数组将仅包含索引 2 之前的项目。如果有索引 #3 我们知道我们必须引用它。
下面的 Perl 单行代码的作用与上面描述的完全一样:
$ perl -F'"' -lane '$F[1]="";$F[2]=substr($F[2],1);$F[3]= "\"" . $F[3] . "\"" if $F[3];print @F' inpu>
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,