从csv文件中删除最后4列的bash方法

从csv文件中删除最后4列的bash方法,bash,csv,sed,awk,cut,Bash,Csv,Sed,Awk,Cut,有没有一种方法可以使用bash删除某些输入CSV文件的最后四列?最后四列的字段长度可能因行而异,因此仅从每行末尾删除一定数量的字符是不够的。如果知道列数,可以使用cut。例如,如果文件有9列,逗号是分隔符: cut -d',' -f -5 但是,这假定csv文件中的数据不包含任何逗号cut也会将引号内的逗号解释为分隔符。如果所有行的字段数相同,则cut可以执行此操作;如果没有,则可以执行awk cut -d, -f1-6 # assuming 10 fields 如果要控制输出分隔符use-

有没有一种方法可以使用bash删除某些输入CSV文件的最后四列?最后四列的字段长度可能因行而异,因此仅从每行末尾删除一定数量的字符是不够的。

如果知道列数,可以使用
cut
。例如,如果文件有9列,逗号是分隔符:

cut -d',' -f -5

但是,这假定csv文件中的数据不包含任何逗号
cut
也会将引号内的逗号解释为分隔符。

如果所有行的字段数相同,则cut可以执行此操作;如果没有,则可以执行awk

cut -d, -f1-6 # assuming 10 fields
如果要控制输出分隔符use--output delimiter=string,将打印出前6个字段

awk -F , -v OFS=, '{ for (i=1;i<=NF-4;i++){ printf $i, }; printf "\n"}'
awk-F,-v OFS=,'{for(i=1;iawk一行:

awk -F, '{for(i=0;++i<=NF-5;)printf $i", ";print $(NF-4)}'  file.csv
awk-F'{for(i=0;++i这可能适合您(GNU-sed):


rev
反转行数,因此不管所有行的列数是否相同,它都会删除最后4列。这仅在最后4列本身不包含任何逗号的情况下才有效。

此awk解决方案采用黑客攻击方式

awk -F, 'OFS=","{for(i=NF; i>=NF-4; --i) {$i=""}}{gsub(",,,,,","",$0);print $0}' temp.txt
或者

awk -F, -vOFS=, '{NF-=4;print}' file.csv

将删除每行的最后4列。

当CVS文件的字段带有带引号的字符时,上述方法都无法正常工作。因此,仅使用-字符作为字段分隔符有点困难

以下两个帖子现在非常方便:

  • (注意:这仅适用于GNU awk)
由于您使用GNU awk,因此可以执行以下两项操作之一:

$ awk -v FPAT='[^,]*|"[^"]+"' -v OFS="," 'NF{NF-=4}1'
或者使用任何awk,您都可以:

$ awk 'BEGIN{ere="([^,]*|\042[^\042]+\042)"
             ere=","ere","ere","ere","ere"$"
       }
       {sub(ere,"")}1'

在awk行中,我想你想打印f$I而不是打印$I,对吧?可能是打字错误?而且
print$I,
不起作用,你可能需要
另一个打字错误?@kent yeah是指打印f$I,你不需要;如果只有一个命令。啊,我明白你的意思。逗号被扩展为OFS变量的值这不是一个强大的met正如您可能在
“field1”,field2,“field3,comma”,field4中引用了带逗号的字段一样,在我看来,这是一个非常好的解决方案,+1用于rev(我不知道它存在)我得到
rev:stdin:0:无效或不完整的多字节或宽字符
似乎我的文件是一个Windows csv文件,带有
小端UTF-16 Unicode文本
。最后我不得不使用
awk
(出于其他原因)删除额外列的好方法,但对我来说,这将在输出中用空格替换列之间的逗号。有没有一种简单的方法可以避免这种情况并将它们保留为逗号?您可以使用awk-F,“{NF-=4;OFS=”,“print}重新添加分隔符“太好了,这对我来说很有用。也可以在
BEGIN
块中设置
OFS
,或者使用
-v
命令行参数,比如
awk-F,-vOFS=,…
这个方法只对GNU awk有效。根据Posix,更改NF是未定义的行为。在我看来,这是最好的答案!”!
awk -F, '{NF-=4; OFS=","; print}' file.csv
awk -F, -vOFS=, '{NF-=4;print}' file.csv
$ awk -v FPAT='[^,]*|"[^"]+"' -v OFS="," 'NF{NF-=4}1'
$ awk 'BEGIN{ere="([^,]*|\042[^\042]+\042)"
             ere=","ere","ere","ere","ere"$"
       }
       {sub(ere,"")}1'