ファイル間で2つのデフォルト列を一致させ、これらのデフォルト列が一致する場合は、追加の列を出力ファイルに貼り付けます。最初のファイルの行サイズを一定に保つ

ファイル間で2つのデフォルト列を一致させ、これらのデフォルト列が一致する場合は、追加の列を出力ファイルに貼り付けます。最初のファイルの行サイズを一定に保つ

これは私が約24時間前に質問した前の質問に対する後続の答えです。ファイル間の主列がすべて一致し、これらの主列が一致した場合は、出力ファイルに補助列を貼り付けます。

G-Manは動作するコードでこの問題を解決しましたが、その後の質問があります。答えを受け入れたので、2番目の投稿は次のようになります。

3つのファイルがあり、各ファイルには一意の数の列があり、すべての列はタブで区切られていますが、一部の列は3つのファイル間で共有されます。これは、一種の「集約」ファイルを生成するために使用したい3つのファイル間の共有列です。

次の表は、これらのファイルの例を示しています。デフォルトでは、MAIN1とMAIN2列の間のファイルを一致させたいと思います。両方の列は3つのファイル間で一致する必要があります。

2つのファイルの間にMAIN1とMAIN2が一致する場合は、file2の "minor8"列をfile1のテーブルの右側に追加したいと思います。後で 2 つのファイルの間に MAIN1 と MAIN2 が一致する場合は、file3 の "minor9" を file1 テーブルの右側に追加したいと思います。 "minor8"はfile1の一番右の列(列名: "minor3")の横にある必要があるため、新しい出力ファイルでは "minor9"が "minor8"の横にあることを望みます。出力ファイルは、理想的な最終ファイルがどのように見えるべきかについてのアイデアを提供します。

デフォルトでは、以下は3つのファイルの例です(「タブ」は少し混乱しています)。

ファイル1:

MAIN1   minor1  MAIN2   minor3
1  bla1    a    blabla1
1  bla2    b    blabla2
1  bla3    c    blabla3
2  bla4    a    blabla4
2  bla5    d    blabla5
3  bla6    e    blabla6
4  bla7    f    blabla7
5  bla8    a    blabla8
5  bla9    g    blabla9

ファイル2:

minor8  MAIN1   MAIN2
yes1    2   d
yes2    3   e
yes3    4   f
yes4    5   a
yes5    5   g
yes6    1   a
yes7    1   b
yes8    1   c
yes9    2   a

ファイル3:

MAIN1   MAIN2   minor9
5   a   sure1
5   g   sure2
1   a   sure3
1   b   sure4
1   c   sure5
2   a   sure6
2   d   sure7
3   e   sure8
4   f   sure9

必須出力ファイル:

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1   bla1    a   blabla1 yes6    sure3
1   bla2    b   blabla2 yes7    sure4
1   bla3    c   blabla3 yes8    sure5
2   bla4    a   blabla4 yes9    sure6
2   bla5    d   blabla5 yes1    sure7
3   bla6    e   blabla6 yes2    sure8
4   bla7    f   blabla7 yes3    sure9
5   bla8    a   blabla8 yes4    sure1
5   bla9    g   blabla9 yes5    sure2

前述のように、G-Manは私が望むものを正確に実行するための便利なコードを提供しています(前の記事を参照)。私はG-Man(または時間がある他の人)に私がよく理解していないコードのいくつかの個々の行についていくつかの具体的な質問をするかもしれませんが、それまでは後続の質問があります。

G-Manのコードは上記のOUTPUTファイルを再生成することができるので、G-Manに感謝します!

フォローアップの質問:

私が言及していないことの1つは、コードが実行されず(私が知っている限り)、MAIN1列とMAIN2列がファイル間で一致しない場合、file1から行を削除することです。これを明示していないのは私のせいです。私の目標は、file1の行が削除されない出力ファイルを持つことです。

デフォルトでは、file1は私の優先順位ファイルです。ファイル内の行数(百万に近い)に関係なく、これはOUTPUTファイルに存在する必要があるかもしれません。 MAIN1、MAIN2列が一致しない場合、一部の行の「minor8」および「minor9」列が空になる可能性があります。しかし、「minor8」または「minor9」(またはその両方)の「欠落/null」値がある場合は、file1の対応する行を保持したいと思います。

上記のファイル2と3のわずかに異なるバージョンを使用してこれを説明しようとしています(したがって、file1は同じままです)。

調整されたファイル2(MAIN1、MAIN2の組み合わせなし:2、d):

minor8  MAIN1   MAIN2
yes2    3   e
yes3    4   f
yes4    5   a
yes5    5   g
yes6    1   a
yes7    1   b
yes8    1   c
yes9    2   a

調整されたファイル3(MAIN1、MAIN2の組み合わせなし:5、a):

MAIN1   MAIN2   minor9
5   g   sure2
1   a   sure3
1   b   sure4
1   c   sure5
2   a   sure6
2   d   sure7
3   e   sure8
4   f   sure9

目的の出力を調整しました(つまり、MAIN1、MAIN2の組み合わせ2-dの場合はMinor8列のNULL、MAIN1、MAIN2の組み合わせ5-aの場合はMinor9列のNULL)。

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1   bla1    a   blabla1 yes6    sure3
1   bla2    b   blabla2 yes7    sure4
1   bla3    c   blabla3 yes8    sure5
2   bla4    a   blabla4 yes9    sure6
2   bla5    d   blabla5     sure7
3   bla6    e   blabla6 yes2    sure8
4   bla7    f   blabla7 yes3    sure9
5   bla8    a   blabla8 yes4    
5   bla9    g   blabla9 yes5    sure2

私が説明する方法が十分に明確であることを願っています。私はテーブルのタブが少し混乱していると思います。これが好きですか、それとも私がテーブルをテーブルに整理するのが好きですか? (これが原因であると考えられる唯一の問題は、サンプルデータをコピーして貼り付けるときにそこにはいけない追加のタブがあることです...)

とにかく、助けてくれてありがとう。近いうちに、単に助けを求めるよりも、このフォーラムに貢献できることを願っています。

これを可能にするためにG-Manのコードを編集する方法に関する提案はありますか?または、これらの追加要件を考慮して有用なコードを記述する方法についてまったく異なる提案がある場合は、お知らせください。

ベストアンサー1

次のファイルを生成します。

merge21:

開始{
        FS="\t"
        OFS = "\t"
}
NR==FNR { #ファイル2
        キー=$2","$3
        存在[キー] = 1
        小さな8[キー] =1
        Next
}
{#ファイル1
        キー=$1 "," $3
        if (現在[キー]) $1, $2, $3, $4,マイナー8 [キー]
        それ以外の場合は、$1、$2、$3、$4、「-」を印刷します。
}

merge312:

開始{
        FS="\t"
        OFS = "\t"
}
NR==FNR { #ファイル3
        キー=$1","$2
        存在[キー] = 1
        小さな9[キー] =$3
        Next
}
{#ファイル1 +ファイル2
        キー=$1 "," $3
        if (現在[キー]) $1, $2, $3, $4,$5、未成年者9 [鍵]
        それ以外の場合は、$1、$2、$3、$4 を印刷します。5ドル、「-」
}

それらはほぼ同じです。違いを太字にしました。ここでコマンドを入力してください。

awk -f merge21 file2 file1 | awk -f merge312 file3 -

これは、キーフィールドにコンマが含まれておらず、データにハイフンが含まれていないと仮定しますが、実際には存在するかどうかによって異なります。一部データに表示されない文字列です。より多くの列をサポートするためにこれを拡張することは容易ではありません。これできる一度にすべてのタスクを実行するように改善できますが、awkこれはもう少し複雑で(IMNSHO)努力する価値はありません。

これにより、ファイル内のデータのいわゆる「左外部結合」が生成されます。INNER接続とOUTER接続の違いいくつかの定義については、スタックオーバーフローを確認してください。 (「左外部結合」は、この質問に対する回答で「最初のテーブルのすべての行と他のテーブルの共通行」として定義(説明)されます。

あなたの出力は次のとおりです

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1       bla1    a       blabla1 yes6    sure3
1       bla2    b       blabla2 yes7    sure4
1       bla3    c       blabla3 yes8    sure5
2       bla4    a       blabla4 yes9    sure6
2       bla5    d       blabla5 -       sure7
3       bla6    e       blabla6 yes2    sure8
4       bla7    f       blabla7 yes3    sure9
5       bla8    a       blabla8 yes4    -
5       bla9    g       blabla9 yes5    sure2

そして当然削除することもできます。-文字対sed(もちろん、実際のデータに実際にハイフンが含まれている場合は、欠落しているデータのプレースホルダとして使用されていない文字または文字列を選択してください。)


ノート

  • FSとはOFS、それぞれ入力フィールド区切り記号と出力フィールド区切り記号です。 (明らかIFSに意味はありませんawk。それは私の間違いでした。)実際には必要ありませんFS="\t"awkタブはデフォルトで入力のフィールド区切り文字として認識されます。 (スペースを含むフィールドを持つことはできますがOFS="\t"、それには興味がないようです)  print $1, $2, $3, $4出力それらの間にラベルがあります。と言わないとOFS="\t"空白で区切られるのでprint $1 "\t" $2 "\t" $3 "\t" $4退屈で読みやすさが落ちます。
  • MAIN1とMAIN2に追加の制約が与えられている場合(たとえば、常に1文字、またはMAIN1は常に数値で、MAIN2は常に文字で始まる),()にカンマは必要ありませんkey。しかし、最初の質問の元のバージョンにはそのような制限はありませんでした。次のデータを考慮してください。

    MAIN1 ($2)         MAIN2 ($3)         badkey = $2 $3         goodkey = $2 "," $3
        2              34151                  234151                   2,34151
       23               4151                  234151                   23,4151
    

    キーフィールド(MAIN1とMAIN2)に表示されない一部の区切り文字がキーに含まれていない場合は、他の行keyに対して同じ値を取得できます。

  • トッピングを捕まえる危険があるので、私はLinuxに何も言わない。ただLinuxに話しかけるだけです。awk何をすべきか教えてください。
  • コードについて
    NR==FNR { # ファイル 3
            キー=$1 "," $2
            存在[キー] = 1
            小さい 9[キー] = $3
            Next
    }
    file3を含む7番目から最後の行を検討してください1 a sure3。明らかに$1= 1$2= a$3=があるので=sure3です。私が表示するためにフラグに設定したことを意味します。key1,apresent[key] = 1present["1,a"]1file3 持つつまり1,a、 = にminor9値があります。行がないため何も設定されていないため、コードの「」部分には=の内容がないことを知って印刷する必要があります。key1,a5,afile3present["5,a"]file1 + file2minor9key5,a-代わりに。名前はpresent私がランダムに選択したものです1,a展示するfile3 (行ではありません)です5,a1表現するには、「TRUE」を使用するのが一般的です。
  • print $1, $2, $3, $4 に変更できます。for (n=1; n<=4; n++) printf "%s\t", $n最後のフィールドにprint 通常(代わりに)を使用するか、次のようにして行を終了する必要があります。次の作業を行うことで、さらに簡素化できます。printfprintf "\n"

            for (n=1; n<=4; n++) printf "%s\t", $n
            if (現在[キー]) major8[キー]を印刷します。
            それ以外の場合は「-」を印刷します。

読んでくださいアーク(1)、これPOSIX仕様awkGNU Awkユーザーガイドと見るawk.infoより多くの情報を知りたいです。

おすすめ記事