使用sed,awk或sort进行csv操作

时间:2014-07-23 19:31:45

标签: bash awk sed

我有一个需要大量操作的csv文件。也许通过使用awk和sed?

输入:

"Sequence","Fat","Protein","Lactose","Other Solids","MUN","SCC","Batch Name"
1,4.29,3.3,4.69,5.6,11,75,"35361305a"
2,5.87,3.58,4.41,5.32,10.9,178,"35361305a"
3,4.01,3.75,4.75,5.66,12.2,35,"35361305a"
4,6.43,3.61,3.56,4.41,9.6,275,"35361305a"

最终输出:

43330075995647
59360178995344
40380035995748
64360275964436

我能够逐步完成其中的一些工作 如何测试超过9.9的特定列并将其替换为9.9?
此外,有没有办法结合任何这些步骤?

删除第一行:

tail -n +2 test.csv > test1.txt

删除逗号:

sed 's/,/ /g' test1.txt > test2.txt

删除引号:

sed 's/"//g' test2.txt > test3.txt

删除第1列和第8列以及
将剩余列重新排序为1,2,6,5,4,3:

sort test3.txt | uniq -c | awk '{print $3 "\t" $4 "\t" $8 "\t" $7 "\t" $6 "\t" $5}' test4.txt

测试新列1,2,4,5,6 - 如果值超过9.9,则将其替换为9.9

How should I do this step?

以下问题的解决方案在前一个问题中找到 - reformating a text file
第1,2,4,5,6列圆形小数到十分之一
第3列需要四个字符长,使用零到左填充
删除句号和空格

awk '{$0=sprintf("%.1f%.1f%4s%.1f%.1f%.1f", $1,$2,$3,$4,$5,$6);gsub(/ /,"0");gsub(/\./,"")}1' test5.txt > test6.txt

3 个答案:

答案 0 :(得分:0)

三人合唱:

awk -F, '{gsub(/"/,"");$1=$1} NR>1' test.csc
1 4.29 3.3 4.69 5.6 11 75 35361305a
2 5.87 3.58 4.41 5.32 10.9 178 35361305a
3 4.01 3.75 4.75 5.66 12.2 35 35361305a
4 6.43 3.61 3.56 4.41 9.6 275 35361305a

答案 1 :(得分:0)

这将从原始文件中生成所需的输出。请注意,在您指定的问题中 - 请注意,在您指定的问题“第4列舍入到整数”但在所需的输出中,您已将其舍入到一个小数位:

awk -F'[,"]+' 'function m(x) { return x < 9.9 ? x : 9.9 } 
NR > 1 { 
    s = sprintf("%.1f%.1f%04d%.1f%.1f%.1f", m($2),m($3),$7,m($6),m($5),m($4))
    gsub(/\./, "", s)
    print s
}' test.csv

我已将字段分隔符指定为任意数量的逗号和双引号,因此这将“解析”您的CSV格式,而无需任何其他步骤。

函数m返回最小值9.9以及传递给它的数字。

输出:

43330075995647
59360178995344
40380035995748
64360275964436

答案 2 :(得分:-1)

tail -n +2 file | sort -u | awk -F , '
    {
        $0 = $1 FS $2 FS $6 FS $5 FS $4 FS $3
        for (i = 1; i <= 6; ++i)
            if ($i > 9.9)
                $i = 9.9
        $0 = sprintf("%.1f%.1f%4s%.0f%.1f%.1f", $1, $2, $3, $4, $5, $6)
        gsub(/ /, "0"); gsub(/[.]/, "")
        print
    }
'

或者

< file awk -F , '
    NR > 1 {
        $0 = $1 FS $2 FS $6 FS $5 FS $4 FS $3
        for (i = 1; i <= 6; ++i)
            if ($i > 9.9)
                $i = 9.9
        $0 = sprintf("%.1f%.1f%4s%.0f%.1f%.1f", $1, $2, $3, $4, $5, $6)
        gsub(/ /, "0"); gsub(/[.]/, "")
        print
    }
'

输出:

104309964733
205909954436
304009964838
406409643636