ファイルがありますA.txt
(9月= \t
)。
Cycle Well Value Target
1 A1 5.07368111264623 EC
1 A1 3.06982862746599 FT
1 A1 2.46545646544623 EC
2番目のファイルB.txt
(sep = \t
、最初の列は空です。):
Well Fluor Target Content Sample
A1 Cy5 EC Unkn-01 2060563935
A1 Cy5 FT Unkn-09 2156515156
Content
次の場合に追加したいB.txt
列を追加したいと思います。A.txt
両方 Well
Target
両方のファイルのデータが同じで、結果を(C.txt
sep = \t
)として出力します。
Cycle Well Value Target Content
1 A1 5.07368111264623 EC Unkn-01
1 A1 3.06982862746599 FT Unkn-09
1 A1 2.46545646544623 EC Unkn-01
私は次のことを試してみます:
awk -F"\t" 'FNR==NR{if (a[$2]) {a[$2]=a[$2] "\t" $7} else {a[$2]=$7}} NR>FNR{split($0,f,"\t"); if (a[f[4]]) $0=$0 "\t" a[f[4]]; print}'
しかし、それはうまくいきませんでした。これを行う方法を知っていますか?
正確:
- テンプレートとして使用される最初のファイル(A.txt)には、同じ細孔とターゲットを持つ複数のリグニンがあります。
- B.txtには、同じ穴/ターゲットの組み合わせを持つ行が1つだけあります。
- ファイルAとファイルBが一致するパターンを持たないことは不可能です。
答え1
最初の解決策は以下を使用します。GNU awkまたはPOSIX awk
編集する:〜のようにエドモートンawk
GNUのみのサポートに対する元の答えが間違っていると彼の意見に書きました。 (GNU文書とPOSIX文書の表現は少し混乱しています。)
GNUドキュメントawk
のタイトル多次元配列POSIX準拠をサポートしていますawk
。バラよりhttps://pubs.opengroup.org/onlinepubs/000095399/utilities/awk.html「多次元」またはを検索してくださいSUBSEP
。これらの配列は実際には1次元です。
GNUawk
もサポート配列の配列これは真の多次元配列です。
このコマンドバージョンにはGNUが必要ですawk
。
awk -F"\t" 'NR == FNR { a[$2][$4] = $5; next } { print $0, a[$2][$4] }' B.txt A.txt > C.txt
POSIX互換バリアント(*)はすべてと互換性awk
がなければなりません。
awk -F"\t" 'NR == FNR { a[$2,$4] = $5; next } { print $0, a[$2,$4] }' B.txt A.txt > C.txt
両方印刷
Cycle Well Value Target
1 A1 5.07368111264623 EC Unkn-01
1 A1 3.06982862746599 FT Unkn-09
1 A1 2.46545646544623 EC Unkn-01
質問によると、Well / Targetキーはファイル内で一意であるため、ファイル内のデータは配列B.txt
に保存されます。a
その後、このデータはファイルのデータに追加されますA.txt
。
フィールド区切り文字を明示的に指定する必要があります。それ以外の場合は、awk
空の列/値は無視されます。
このソリューションは、固定列番号を使用して一致または印刷する列を識別します。
編集する:\t
索引式と区切り文字を明示的に組み合わせる次の解決策は、上記のPOSIX準拠の解決策(*)と比較して利点を提供しません。
awk -F"\t" 'NR == FNR { a[$2 "\t" $4] = $5; next } { print $0, a[$2 "\t" $4] }' B.txt A.txt > C.txt
これは構文を設定しSUBSEP = "\t"
て使用するのと同じですa[$2, $4]
。
2番目の解決策は以下を使用します。キュー
ツールqは、CSVファイルに対してデータベースと同様のクエリを実行するために使用できます。
バラよりhttp://harelba.github.io/q/またはhttps://github.com/harelba/q
このソリューションには次の問題があります。の列ヘッダーが空ですB.txt
。回避策として、Empty
ファイルのヘッダー行にヘッダーを追加しました。
だから私は次のファイルを使用します。
A.txt
Cycle Well Value Target
1 A1 5.07368111264623 EC
1 A1 3.06982862746599 FT
1 A1 2.46545646544623 EC
B.txt
Empty Well Fluor Target Content Sample
A1 Cy5 EC Unkn-01 2060563935
A1 Cy5 FT Unkn-09 2156515156
注文する
q -H -t "select a.Cycle,a.Well,a.Value,a.Target,b.Content from A.txt as a inner join B.txt as b on a.Well=b.Well and a.Target=b.Target"
印刷
1 A1 5.07368111264623 EC Unkn-01
1 A1 3.06982862746599 FT Unkn-09
1 A1 2.46545646544623 EC Unkn-01
タイトルを印刷するには、printf
またはecho
コマンドを追加できます。
printf "Cycle\tWell\tValue\tTarget\tContent\n" > C.txt
q -H -t "select a.Cycle,a.Well,a.Value,a.Target,b.Content from A.txt as a inner join B.txt as b on a.Well=b.Well and a.Target=b.Target" >> C.txt
B.txt
利用可能なファイルを自動的に変更するには
printf "Empty" > B1.txt
cat B.txt >> B1.txt
printf "Cycle\tWell\tValue\tTarget\tContent\n" > C.txt
q -H -t "select a.Cycle,a.Well,a.Value,a.Target,b.Content from A.txt as a inner join B1.txt as b on a.Well=b.Well and a.Target=b.Target" >> C.txt
ソリューションは、ヘッダー行の名前付き列を使用して、一致または印刷する列を識別します。
答え2
2D配列用のGNUがあると仮定すると、awk
次のプログラムはこれを行います。
awk -F'\t' 'NR==FNR&&FNR>1{map[$2][$4]=$5}\
NR>FNR{if (FNR==1) {$5="Content"} else {$5=map[$2][$4]}} NR>FNR' B.txt A.txt > C.txt
まず、B.txt
特定の「ウェル」と「ターゲット」の組み合わせに対する「コンテンツ」値のマッピング生成を処理します。後で処理するときA.txt
( で示されるFNR
、ファイルごとのラインカウンタが現在のグローバルNR
ラインカウンタよりも小さい)、プログラムは現在のラインで「Well」と「Target」の特定の組み合わせを探し、その「」を置き換えます。以前に作成されたマップコンテンツの値。2番目のファイルを処理した後にのみ出力を印刷します(「stray」のNR>FNR
場合)。