私はbashスクリプトを作成していますが、プロセスの一部では、列の整合性を維持しながらcsvファイルを一緒にリンクする必要があります。たとえば、次の形式の2つのファイルがあります。
F1
ID,MD,L1,L2,L3,GD,L4
12,OB,AA,PP,AA,TT,AA
15,OB,PP,PP,PP,TT,AA
F2
ID,MD,L7,L8,L9,L10,GD
13,OB,PP,AA,AA,AA,AA
15,OB,PP,PP,PP,AA,AA
出力は次のとおりです。ここで、一致しないID戻り値はNMであり、重複列(この場合は「GD」)は各ファイルの値に基づいて表示されます。
ID,MD,L1,L2,L3,GD,L4,L7,L8,L9,L10,GD
12,OB,AA,PP,AA,TT,AA,NM,NM,NM,NM,NM
13,NM,NM,NM,NM,NM,NM,PP,AA,AA,AA,AA
15,OB,PP,PP,PP,TT,AA,PP,PP,PP,AA,AA
私はjoin
それが有望に見えるので、それをやってきました。join -t, -eNM -a1 -a2 -o 0,1.2,1.3,1.4,1.5,1.6,1.7,1.8,2.3,... F1 F2
しかし、いくつかの問題が発生しました。
このオプションを使用すると、
-o
各ファイルごとに独立して異なる正確な列数がわかっていると仮定します。結果でエラーが発生しました:
join: REPORT_2|15-10-2019|15:39:25.csv:5: is not sorted: 04181646
代替案があればjoin
提案を受け入れます。ありがとうございます。
答え1
シェルスクリプトを使用して必要な-o
オプションを生成し、入力ファイルのデータを並べ替えることができます。
これは、2番目のフィールドが両方のMD
入力ファイルに存在し、出力から1回だけ印刷されると仮定します(2番目のファイルのオプションではスキップしました)。
#!/bin/bash
opts="0,"
# file1: get number of columms - 1 from the first line
numcols=$(awk -F',' '(NR==1) {print NF-1}' "$1")
# file1: add options
for i in $(seq "$numcols"); do
opts+=$(printf '1.%s,' "$((i+1))")
done
# file2: get number of columms - 2 from the first line
numcols=$(awk -F',' '(NR==1) {print NF-2}' "$2")
# file2: add options
for i in $(seq "$numcols"); do
opts+=$(printf '2.%s,' "$((i+2))")
done
opts=${opts:0:-1} # remove the last `,`
join -t, --header -eNM -a1 -a2 -o "$opts"\
<(head -n1 "$1"; tail -n+2 "$1" | sort -nk1,1)\
<(head -n1 "$2"; tail -n+2 "$2" | sort -nk1,1)
--header
最初の行をヘッダー行として扱うオプションを追加しました。<(head -n1 "$1"; tail -n+2 "$1" | sort -nk1,1)
ヘッダー行を印刷し、最初のフィールドに基づいて残りの行を数値でソートするために使用されます。
スクリプトを実行可能にする
chmod +x join.sh
次のように実行します。
./join.sh file1 file2
答え2
ミラーの使用(https://github.com/johnkerl/miller)、あなたは実行することができます
mlr --csv join -u --ul --ur -j ID -f input_01.csv \
then unsparsify \
then put -S 'for (k in $*) { if ($[k] =~ "^$") { $[k]="NM" }}' \
input_02.csv
そして得る
ID,MD,L7,L8,L9,L10,L1,L2,L3,L4
13,OB,PP,AA,AA,AA,NM,NM,NM,NM
15,OB,PP,PP,PP,AA,PP,PP,PP,AA
12,OB,NM,NM,NM,NM,AA,PP,AA,AA