これは私が約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
です。私が表示するためにフラグに設定したことを意味します。key
1,a
present[key] = 1
present["1,a"]
1
file3
持つつまり1,a
、 = にminor9
値があります。行がないため何も設定されていないため、コードの「」部分には=の内容がないことを知って印刷する必要があります。key
1,a
5,a
file3
present["5,a"]
file1 + file2
minor9
key
5,a
-
代わりに。名前はpresent
私がランダムに選択したものです1,a
。展示するfile3
(行ではありません)です5,a
。1
表現するには、「TRUE」を使用するのが一般的です。 print $1, $2, $3, $4
に変更できます。for (n=1; n<=4; n++) printf "%s\t", $n
最後のフィールドにprint
通常(代わりに)を使用するか、次のようにして行を終了する必要があります。次の作業を行うことで、さらに簡素化できます。printf
printf "\n"
for (n=1; n<=4; n++) printf "%s\t", $n if (現在[キー]) major8[キー]を印刷します。 それ以外の場合は「-」を印刷します。
読んでくださいアーク(1)、これPOSIX仕様awk
、
GNU Awkユーザーガイドと見るawk.infoより多くの情報を知りたいです。