2つのCSVファイルがあります。1.csv
彼らに電話しましょう2.csv
最初の(
1.csv
)は次のようになります。1,3543 23,3632 12,7665 1,9795 32,8793 35,0290
2番目のファイル(
2.txt
)は次のとおりです。1,4543 3,3223 4,1213 6,2324 65,3123 32,5432 9,9839 5,8798
最後の列は最初の列と最初の列の
output.csv
違いです。1.csv
2.txt
1,3543,1,4543,0 23,3632,3,3223,20 12,7665,4,1213,8 1,9795,6,2324,-5 32,8793,65,3123,-23 35,0290,32,5432,3 ,,9,9839,NA ,,5,8798,NA
私はシェルスクリプトに初めて触れました。助けてください
答え1
問題は、2つのファイルを結合する共通フィールドがないことです。すぐに 1 つを作成してから awk を再利用して、次のように差を計算できます。
join -a2 -o auto -t, <(awk '{ print NR","$0 }' 1.txt ) <(awk '{ print NR","$0 }' 2.txt) \
| awk 'BEGIN {
FS=OFS=","
}
{ if ($2) {
$6=$2-$4
} else {
$6="NaN"
};
print $2,$3,$4,$5,$6
}'
1,3543,1,4543,0
23,3632,3,3223,20
12,7665,4,1213,8
1,9795,6,2324,-5
32,8793,65,3123,-33
35,0290,32,5432,3
,,9,9839,NaN
,,5,8798,NaN
答え2
両方のファイルを一緒に貼り付けると、結果全体を処理できます。
paste -d, 1.txt 2.txt |
awk -F, 'NF < 4 { printf $1=="" ? ",%s,NA\n" : "%s,,NA\n", $0 }
NF >= 4 { printf "%s,%d\n", $0, $1-$3 }'
これはコンマを使用して2つのファイルをリンクします。他のファイルに一致する行がない場合は、空のフィールドで始まるか(2番目のファイルが長い場合)、空のフィールドで終わる短い行が生成されます(最初のファイルが長い場合)。 AWKを使用して結果を処理します。
- フィールド数が4つ未満の場合、データは失われます。追加フィールド(前にまたは後に続く)がある行には、「NA」が追加されて出力されます。
- フィールド数が4つ以上の場合、すべてのデータが存在し、その後にフィールド1と3の差が出力されます。
答え3
paste -d : 1.txt 2.txt |
awk -F : -v OFS=, '
{
split($1,a,OFS)
split($2,b,OFS)
$1 = a[1]; $2 = a[2]
$3 = b[1]; $4 = b[2]
}
{
$5 = $1 == "" || $3 == "" ? "NA" : $1 - $3
}; 1'
:
これにより、.aを区切り文字として使用して2つのファイルを並べてリンクしますpaste
。
コマンドはawk
前処理ブロックと計算ブロックに分けられます。
前処理ブロックは、各レコードに各ファイルに2つのフィールドがあることを確認します。
各入力ラインから2つの別々のフィールドを取得し、各入力ラインのコンマ区切りのサブ:
フィールドを2つの配列に抽出しますa
。b
各アレイで予想される2つの要素は、最初の4つのフィールドに直接送信されます。ファイルの1つが他のファイルより短い場合は、空のフィールドが作成されます。
2番目のブロックは、5番目のフィールドを1番目と3番目のフィールドの差として計算します。ただし、フィールドの1つが空でない場合は、5番目のフィールドに文字列が割り当てられますNA
。
前処理ブロックが各ファイルに固定された数のフィールドを使用して、任意の数の入力ファイルに一般化される方法を考えてみましょう。
paste -d : 1.txt 2.txt |
awk -F : -v OFS=, -v nf=2 '
{
for (i = NF; i >= 1; --i) {
split($i,a,OFS)
for (j = 1; j <= nf; ++j)
$((i-1)*nf + j) = a[j]
}
}
{
$5 = $1 == "" || $3 == "" ? "NA" : $1 - $3
}; 1'
nf
これは、各ファイルの予想フィールド数をコマンドラインの引数として渡し、これらのフィールドをnf
それぞれの:
区切り入力フィールド(空であるかどうかにかかわらず)に割り当てることによって問題を解決します。
最終計算ブロックは以前と同じです。awk
コードの最初の部分を将来のニーズやその他の場所で再利用できるように、柔軟性を高めました。
答え4
paste g1.txt g2.txt|awk '{print $1","$2}'| awk -F "," '{if (NF==4){print $0","$1-$3}else{print ",,"$0"NA"}}'
出力
1,3543,1,4543,0
23,3632,3,3223,20
12,7665,4,1213,8
1,9795,6,2324,-5
32,8793,65,3123,-33
35,0290,32,5432,3
,,9,9839,NA
,,5,8798,NA