0

我有一些数据文件,我想为其生成一个“差异”列,这意味着添加一个列来指示是否已从当前文件中添加/删除了特定行。例如,我有以下两个文件a.csv

id,data,data2
1,A,B
2,A,B
3,A,B
4,A,B

b.csv

id,data,data2
2,A,C
3,A,C
4,A,C
5,A,C

我只想根据id是否添加/删除行进行比较。数据无所谓。到目前为止,我想出的最好的方法是以以下方式使用miller :

#!/bin/bash

t1=$(mktemp)
t2=$(mktemp)
t3=$(mktemp)

mlr --icsv --ocsv put '$diff = "-"' then reorder -f diff a.csv > "$t1"
mlr --icsv --ocsv put '$diff = "+"' then reorder -f diff b.csv > "$t2"
mlr --icsv --ocsv join -f "$t1" -j id --ul --ur --np then unsparsify "$t2" > "$t3"
mlr --icsv --ocsv join -f "$t3" -j id --ul --ur      then unsparsify then reorder -f diff,id then sort -nf id b.csv

rm "$t1"
rm "$t2"
rm "$t3"

这会生成以下内容,这就是我想要的:

diff,id,data,data2
-,1,A,B
,2,A,C
,3,A,C
,4,A,C
+,5,A,C

该解决方案的不幸之处在于它需要运行 miller 四次并使用三个临时文件。Miller 似乎不适用于 bash 流程替换(<()业务)。

有没有更直接的方式来产生这种输出?

4

2 回答 2

0

有一个专门的工具:https ://github.com/paulfitz/daff 。

如果您在示例 daff a.csv b.csv 中运行,您将获得

---,1 ,A ,B → ,2 ,A ,B→C → ,3 ,A ,B→C → ,4 ,A ,B→C +++,5 ,A ,C

于 2018-12-10T17:37:20.287 回答
0

以下输出与您发布的完全相同:

join -t, -11 -22 <(
        # the order of files here is important
        # filter out duplicates too
        sort -t, -u -k1,1 b.csv a.csv
    ) <(
        comm --output-delimiter=, <(
                <a.csv \
                cut -d, -f1 |
                sort
            ) <(
                <b.csv \
                cut -d, -f1 |
                sort
            ) | 
        # this is stupid, but needs to be done anyway
        sed '
            s/^,,/,/;t;
            s/^,/+,/;t;
            s/^/-,/
        '
    ) |
awk -vFS=, -vOFS=, '{print $4,$1,$2,$3}'

但是我们可以通过join -o auto简单的方式变得更短awk

join -t, -11 -21  -a1 -a2 -o auto a.csv b.csv | 
awk -vFS=, -vOFS=, '{
    $6=""
    if (length($2) == 0) { $6="+"; $2=$4; $3=$5; }
    else if (length($4) == 0) { $6="-"; }
    else { $2=$4; $3=$5; }
    print $6,$1,$2,$3
}'

我有一种奇怪的感觉,我会保留data2两个文件中的列,因为它们不同,并且真正简化了思考,只需:

join -t, -11 -21  -a1 -a2 -o auto a.csv b.csv | 
awk -vFS=, -vOFS=, '{
    $6=""
    if (length($2) == 0) $6="+"
    if (length($4) == 0) $6="-"
    print $6,$1,$2,$3,$4,$5
}'

输出:

-,1,A,B,,
,2,A,B,A,C
,3,A,B,A,C
,4,A,B,A,C
+,5,,,A,C

这被解释为:

# diff, id, data from a.csv, data2 from a.csv, data from b.csv, data2 from b.csv

现场版在tutorialspoint可用。

于 2018-12-10T18:10:08.353 回答