如何从嵌套-csv文件中删除子列?

时间:2016-01-30 07:42:12

标签: python perl csv awk sed

给出一个空格分隔的文件:

0.0 1:0.000000 2:1.000000 3:0.000000 4:0.000000 5:1.000000 6:0.000000 7:1.000000 8:1.000000 9:1.000000 10:1.000000 11:1.000000 12:1.000000 13:1.000000 14:1.000000 15:0.919033 16:1.000000 17:1.000000 18:1.000000 19:1.000000 20:0.000000 21:0.037771
0.0 1:0.000000 2:1.000000 3:0.000000 4:0.000000 5:1.000000 6:0.000000 7:1.000000 8:0.800000 9:0.666667 10:1.000000 11:0.800000 12:0.666667 13:1.000000 14:0.875000 15:0.874574 16:0.848662 17:0.901802 18:0.938795 19:0.903077 20:0.333332 21:0.196682
0.0 1:1.098612 2:1.000000 3:1.000000 4:0.000000 5:1.000000 6:0.000000 7:1.000000 8:0.800000 9:0.500000 10:0.000000 11:0.800000 12:0.500000 13:0.000000 14:0.909091 15:0.780985 16:0.792052 17:0.865396 18:0.863982 19:0.832962 20:0.000000 21:0.069470
0.0 1:0.000000 2:1.000000 3:0.000000 4:0.000000 5:1.000000 6:0.000000 7:1.000000 8:0.923077 9:0.909091 10:0.888889 11:0.923077 12:0.909091 13:0.888889 14:0.943396 15:0.923562 16:0.923871 17:0.949357 18:0.950790 19:0.944919 20:0.142857 21:0.140054

第一列都是0.0,我们希望将第一列扔掉。然后对于每一列,有一个冒号将键与其值分开。而目标只是保持价值。

我可以在python

中这样做
with io.open(infile, 'r') as fin:
    for line in fin:
        line = line.split()[1:]
        line = '\t'.join([i.split(':')[1] for i in line])
        print line

[OUT]:

0.000000    1.000000    0.000000    0.000000    1.000000    0.000000    1.000000    1.000000    1.000000    1.000000    1.0000001.000000    1.000000    1.000000    0.919033    1.000000    1.000000    1.000000    1.000000    0.000000    0.037771
0.000000    1.000000    0.000000    0.000000    1.000000    0.000000    1.000000    0.800000    0.666667    1.000000    0.8000000.666667    1.000000    0.875000    0.874574    0.848662    0.901802    0.938795    0.903077    0.333332    0.196682
1.098612    1.000000    1.000000    0.000000    1.000000    0.000000    1.000000    0.800000    0.500000    0.000000    0.8000000.500000    0.000000    0.909091    0.780985    0.792052    0.865396    0.863982    0.832962    0.000000    0.069470
0.000000    1.000000    0.000000    0.000000    1.000000    0.000000    1.000000    0.923077    0.909091    0.888889    0.9230770.909091    0.888889    0.943396    0.923562    0.923871    0.949357    0.950790    0.944919    0.142857    0.140054

但是在unix命令行上是如何实现的?(可能与sedawkperl -c甚至python -c或其他任何事情)想象一下它是一个大文件,所以请不要将整个文件加载到内存中,除非这是一个经济上的原因。

5 个答案:

答案 0 :(得分:2)

使用GNU sed:

sed 's/^0.0 //;s/[0-9]\+:\([0-9.]\+\)/\1/g' file

输出:

0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 0.919033 1.000000 1.000000 1.000000 1.000000 0.000000 0.037771
0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 1.000000 0.800000 0.666667 1.000000 0.800000 0.666667 1.000000 0.875000 0.874574 0.848662 0.901802 0.938795 0.903077 0.333332 0.196682
1.098612 1.000000 1.000000 0.000000 1.000000 0.000000 1.000000 0.800000 0.500000 0.000000 0.800000 0.500000 0.000000 0.909091 0.780985 0.792052 0.865396 0.863982 0.832962 0.000000 0.069470
0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 1.000000 0.923077 0.909091 0.888889 0.923077 0.909091 0.888889 0.943396 0.923562 0.923871 0.949357 0.950790 0.944919 0.142857 0.140054

如果您要“就地”修改文件,请添加sed的选项-i

两个以;分隔的sed脚本:

  

s/^0.0 //:从^的行首(0.0)开始搜索后跟空格并替换为空白

     

s/[0-9]\+:\([0-9.]\+\)/\1/g:搜索范围+0中的至少一个(9)字符,后跟:,后跟至少一个( +09.范围内的字符,并通过圆括号中的匹配部分替换它。 \1是对圆括号中匹配部分的后引用。 g表示将替换应用于正则表达式的所有匹配,而不仅仅是第一个匹配。对于带有here: +的sed,必须转义特殊字符(()\)。

更短的版本:

sed 's/^0.0 //;s/[0-9]\+://g' file

请参阅:The Stack Overflow Regular Expressions FAQ

答案 1 :(得分:2)

awk救援!

$ awk '{gsub("[^ ]*:","");sub("[^ ]* ","")}1' file 

0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 0.919033 1.000000 1.000000 1.000000 1.000000 0.000000 0.037771
0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 1.000000 0.800000 0.666667 1.000000 0.800000 0.666667 1.000000 0.875000 0.874574 0.848662 0.901802 0.938795 0.903077 0.333332 0.196682
1.098612 1.000000 1.000000 0.000000 1.000000 0.000000 1.000000 0.800000 0.500000 0.000000 0.800000 0.500000 0.000000 0.909091 0.780985 0.792052 0.865396 0.863982 0.832962 0.000000 0.069470
0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 1.000000 0.923077 0.909091 0.888889 0.923077 0.909091 0.888889 0.943396 0.923562 0.923871 0.949357 0.950790 0.944919 0.142857 0.140054

答案 2 :(得分:1)

awk可以做到这一点:

// {
    for(i=2; i<=NF; i++)
    {
        split($i, array, ":")
        printf("%s\t", array[2])
    }
    printf("\n")
}

解释//表示&#34;对于每一行&#34; (实际上,它匹配所有可能的字符序列),for每个字段从2到最后一个(NF),split i :上的字段并将每个部分存储在array中(从1开始,因此array[2]是第二部分)和printf。在每一行的末尾,打印换行符。

修改

这是我的第一个答案,但我在删除每列的其他部分时略过了一点。

您可以使用cut命令:例如,如果您只需删除第一列,则可以编写

cut -c2- yourfile

解释-c可让您选择要保留的列,2-表示&#34;来自第二个&#34;。

答案 3 :(得分:1)

为什么不使用该模块:

use Text::CSV;

它已经提供了将CSV文件轻松解析为结构的功能,并且还以另一种方式将结构解析为CSV文件。

然后,您可以选择要保留或删除的列。

答案 4 :(得分:1)

使用perl很容易:

perl -ne 'print join ( "\t", m/:([\d\.]+)/g ),"\n"' file_to_parse

此:

  • 逐行迭代(-n将其包裹在while ( <> ) {循环中)
  • 使用正则表达式:m/:([\d\.]+)/g之后提取数值(并重复执行此操作)。我假设digits and .但实际上你可以m/:(\S+)/g如果有任何非空白&#39}没问题(如你的例子)。
  • 您的第一个字段不包含:,因此省略它
  • 打印,标签分隔

输出:

0.000000    1.000000    0.000000    0.000000    1.000000    0.000000    1.000000    1.000000    1.000000    1.000000    1.000000    1.000000    1.000000    1.000000    0.919033    1.000000    1.000000    1.000000    1.000000    0.000000    0.037771
0.000000    1.000000    0.000000    0.000000    1.000000    0.000000    1.000000    0.800000    0.666667    1.000000    0.800000    0.666667    1.000000    0.875000    0.874574    0.848662    0.901802    0.938795    0.903077    0.333332    0.196682
1.098612    1.000000    1.000000    0.000000    1.000000    0.000000    1.000000    0.800000    0.500000    0.000000    0.800000    0.500000    0.000000    0.909091    0.780985    0.792052    0.865396    0.863982    0.832962    0.000000    0.069470
0.000000    1.000000    0.000000    0.000000    1.000000    0.000000    1.000000    0.923077    0.909091    0.888889    0.923077    0.909091    0.888889    0.943396    0.923562    0.923871    0.949357    0.950790    0.944919    0.142857    0.140054