LoginSignup
2
2

More than 5 years have passed since last update.

csv のほどよい完全外部結合

Posted at

問題

で、 join コマンドを用いて完全外部結合を行う方法が示されている。ただ、output のフォーマットを毎回指定するのはめんどい。かといってフォーマットがないと、下みたいに列がそろわず、あまりよくない感じで join されてしまう。具体的には、外部結合部分の、行の列の数が、異なって出力されてしまう。

problem-example
: 1.csv
hoge,100
fuga,200
piyo,300

: 2.csv
hoge,Adam
fuga,Bill
moge,Charlie

$ join -a 1 -a 2 -t, -j 1 1.csv 2.csv
hoge,100,Adam
fuga,200,Bill
moge,Charlie
piyo,300

解決方法

output のフォーマットを生成しながら join を実行することにより、この問題を解決する。

nice-join.sh
#!/bin/bash

if [ $# -ne 2 ]
then
    echo "usage: $0 [-j num_field ][ -1 num_field1 ] [ -2 num_field2 ] 1.csv 2.csv" 1>&2
    exit 1
fi

j1_field=1
j2_field=1

while true; do
    case "$1" in
        -j)
            j1_field="$2"
            j2_field="$2"
            shift 2
            ;;
        -1)
            j1_field="$2"
            shift 2
            ;;
        -2)
            j2_field="$2"
            shift 2
            ;;
        *)
            break
            ;;
    esac
done

count_commas() {
    sed 's/[^,]//g' | wc -c
}

make_format() {

    if [ $# -ne 3 ]
    then
        echo "usage: $0 file_num join_field num_commas" 1>&2
        exit 1
    fi

    seq 1 $3 |
        grep -v $2 |
        awk -v num=$1 '{printf ("%s.%s\n",num,$0)}' |
        { tr '\n' , ; echo; } |
        sed 's/,$//'
}

cat "$1" | {
    exec 3<&0
    read -r line1
    num_commas1=$(printf '%s\n' "$line1" | count_commas)
    format1=$(make_format 1 $j1_field $num_commas1)
    cat "$2" | {
        read -r line2
        num_commas2=$(printf '%s\n' "$line2" | count_commas)
        format2=$(make_format 2 $j2_field $num_commas2)
        join -o 0,$format1,$format2 \
             -a 1 -a 2 -t, \
             -1 $j1_field -2 $j2_field <(
            printf '%s\n' "$line1"
            cat <&3
        ) <(
            printf '%s\n' "$line2"
            cat
        )
    }
    exec 3<&-
}
how-to-use
$ nice-join.sh 1.csv 2.csv
hoge,100,Adam
fuga,200,Bill
moge,,Charlie
piyo,300,
2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2