按顺序合并.csv中的行

时间:2015-05-08 21:45:50

标签: bash csv awk

在分析脑部扫描后,我最终得到了大约1000个.csv文件,每次扫描一个。我已按顺序将它们合并为一个(按主题ID和日期)。我的问题是,一些受试者有两次或多次连续扫描,有些只有一次。数据库现在看起来像这样:

ID, CC_area, CC_perimeter, CC_circularity
024_S_0985, 407.00, 192.15, 0.138530          //first scan of A
024_S_0985, 437.50, 204.80, 0.131074          //second scan of A
024_S_0985, 400.75, 198.80, 0.127420          //third scan  of A
024_S_1063, 544.50, 214.34, 0.148939          //first and only scan of B
024_S_1171, 654.75, 240.33, 0.142453          //first scan of C
024_S_1171, 659.50, 242.21, 0.141269          //second scan of C
...

但我希望它看起来像那样:

ID, CC_area, CC_perimeter, CC_circularity, CC_area2, CC_perimeter2, CC_circularity2, CC_area3, CC_perimeter3, CC_circularity3, ..., CC_circularity6
024_S_0985, 407.00, 192.15, 0.138530, 437.50, 204.80, 0.131074, 400.75, 198.80, 0.127420, ... , 
024_S_1063, 544.50, 214.34, 0.148939,,,,,, ..., 
024_S_1171, 654.75, 240.33, 0.142453, 659.50, 242.21, 0.141269,,, ... , 
...

重要的是,不得更改数据顺序,并且不知道一个ID的行数(从1到6不等)。 (因此扫描1的第一列,然后扫描2等)。你能用bash帮我或提供解决方案吗?我没有编程经验,我已经失去了希望,我可以自己做。

2 个答案:

答案 0 :(得分:1)

您可以使用普通while read循环组合具有相同文件名(或初始索引)的行,然后根据3个条件进行操作。 (1)是否是标题后面的第一行; (2)当前索引等于最后一个;和(3)当前索引与上一个索引不同。有很多方法可以解决这个问题,但是一个简短的bash脚本可能如下所示:

#!/bin/bash

fn="${1:-/dev/stdin}"       ## accept filename or stdin

[ -r "$fn" ] || {           ## validate file is readable
    printf "error: file not found: '%s'\n" "$fn"
    exit 1
}

declare -i cnt=0            ## flag for 1st iteration

while read -r line; do      ## for each line in file

    ## read header, print & continue
    [ ${line//,*/} = ID ] && printf "%s\n" "$line" && continue

    line="${line//  */}"            ## strip //first scan of A....
    idx=${line//,*/}                ## parse file index from line
    line="${line#*, }"              ## strip index

    if [ $cnt -eq 0 ]; then         ## if first line - print
        printf "%s, %s" "$idx" "$line"
        ((cnt++))
    elif [ $idx = $lidx ]; then     ## if indexes equal, append
        printf ", %s" "$line"
    else                            ## else, newline & print
        printf "\n%s, %s" "$idx" "$line"
    fi

    last="$line"            ## save last line
    lidx=$idx               ## save last index

done <"$fn"

printf "\n"

<强>输入

$ cat dat/cmbcsv.dat
ID, CC_area, CC_perimeter, CC_circularity
024_S_0985, 407.00, 192.15, 0.138530          //first scan of A
024_S_0985, 437.50, 204.80, 0.131074          //second scan of A
024_S_0985, 400.75, 198.80, 0.127420          //third scan  of A
024_S_1063, 544.50, 214.34, 0.148939          //first and only scan of B
024_S_1171, 654.75, 240.33, 0.142453          //first scan of C
024_S_1171, 659.50, 242.21, 0.141269          //second scan of C

<强>输出

$ bash cmbcsv.sh dat/cmbcsv.dat
ID, CC_area, CC_perimeter, CC_circularity
024_S_0985, 407.00, 192.15, 0.138530, 437.50, 204.80, 0.131074, 400.75, 198.80, 0.127420
024_S_1063, 544.50, 214.34, 0.148939
024_S_1171, 654.75, 240.33, 0.142453, 659.50, 242.21, 0.141269

注意:我不知道您是否需要所有额外的逗号或省略号,或者他们是否只是在那里显示可能有更多相同的索引(例如{{1} })。如果需要,您可以轻松添加它们。

答案 1 :(得分:0)

如果您知道哪个扫描属于哪个人,您可以添加额外的列,例如患者姓名或身份证,但我想如果您拥有每人扫描数量的原始信息