Unix 截断 csv 文件中的列

Unix 截断 csv 文件中的列

如何从 Unix 命令行将“test10”列截断为 5 个字符?

由此

test1,test2,test3,test4,test10,test11,test12,test17
rh,mbn,ccc,khj,ee3 eeeeeEeee ee$eeee e.eeeee2eeeee5eeeeeeee,a2,3,u
hyt,bb,mb,khj,R ee3ee eeEeee ee$eeee e.eeeee2eeeee5eeeeeeee,a,5,r
mbn,htr,ccc,fdf,F1ee eeeeEeee ee$eeee e.eeeee2eeeee5eeeeeeee,a,e,r

对此

test1,test2,test3,test4,test10,test11,test12,test17
rh,mbn,ccc,khj,ee3 e,a2,3,u
hyt,bb,mb,khj,R ee3,a,5,r
mbn,htr,ccc,fdf,F1ee ,a,e,r

答案1

如果您的文件确实像您的示例一样简单,您可以执行以下操作之一:

  • awk

    $ awk -F, -vOFS=, 'NR>1{$5=substr($5,1,5)}1' file 
    test1,test2,test3,test4,test10,test11,test12,test17
    rh,mbn,ccc,khj,ee3 e,a2,3,u
    hyt,bb,mb,khj,R ee3,a,5,r
    mbn,htr,ccc,fdf,F1ee ,a,e,r
    

    解释

    -F,输入字段分隔符设置为,并将-vOFS=,变量OFS(输出字段分隔符)设置为,NR是当前行号,因此上面的脚本会将第 5 个字段更改为其自身的 5 个字符的子字符串。唯一的一个1是 awk 的“打印这一行”的简写。

  • perl

    $ perl -F, -lane '$F[4]=~s/(.{5}).*/$1/ if $.>1; print join ",", @F' file 
    test1,test2,test3,test4,test10,test11,test12,test17
    rh,mbn,ccc,khj,ee3 e,a2,3,u
    hyt,bb,mb,khj,R ee3,a,5,r
    mbn,htr,ccc,fdf,F1ee ,a,e,r
    

    解释

    使-aperl 的行为类似于 awk 并根据 给定的字符分割其输入行-F并将它们保存为数组的元素@F。然后,我们删除第 5 个字段中除前 5 个字符之外的所有字符(它们从 开始计数0),然后打印@F用逗号连接的结果数组。

  • sed

    $ sed  -E '1!s/(([^,]+,){4}[^,]{5,5})[^,]*,/\1,/' file
    test1,test2,test3,test4,test10,test11,test12,test17
    rh,mbn,ccc,khj,ee3 e,a2,3,u
    hyt,bb,mb,khj,R ee3,a,5,r
    mbn,htr,ccc,fdf,F1ee ,a,e,r
    

    解释

    这是替换运算符,其一般格式为s/original.replacement/。意思1!是“不要在第一行这样做”。正则表达式匹配一组非字符,,后跟,4 次 ( ([^,]+,){4}),然后是任何 5 个非,字符 ( [^,]{5})(这些是第 5 个字段的第 1 个 5),然后是其他任何字符,直到字段末尾 ( [^,]+,)。所有这些都被该行的第一部分替换,有效地截断了该字段。

答案2

使用awk

awk -F , 'BEGIN { OFS = FS } NR > 1 { $5 = substr($5,1,5) }; 1' data.csv

-F标志设置输入字段分隔符,该BEGIN块将输出字段分隔符设置为输入字段分隔符(逗号)。

如果当前记录的序号 ( NR) 大于 1(即我们已经传递了标题行),则该substr()函数会将第五个字段(列)截断为最多 5 个字符。这可以避免修改输入数据的第一行。

单独的1将导致将awk(可能)修改的记录(行)打印到标准输出。

相关内容