2つのCSVファイルをマージして、もう1つの列がある1つのCSVファイルを作成します。

2つのCSVファイルをマージして、もう1つの列がある1つのCSVファイルを作成します。

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.csv2.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つの配列に抽出しますab各アレイで予想される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

関連情報