
UnixでExcelのvlookup機能に似た機能を作成するにはどうすればよいですか?
オフィスホームページから抜粋、ルックアップテーブル
VLOOKUPのVは垂直を意味します。比較値が探しているデータの左側の列にある場合は、HLOOKUPの代わりにVLOOKUPを使用してください。
構文 VLOOKUP(lookup_value,table_array,col_index_num,range_lookup)
Lookup_valueテーブル配列の最初の列から取得する値。 Lookup_valueは値または参照です。 lookup_valueがtable_arrayの最初の列の最小値より小さい場合、VLOOKUPは#N / Aエラー値を返します。
Table_array 2 つ以上のデータ列です。範囲または範囲名への参照を使用します。 table_arrayの最初の列の値は、lookup_valueで取得した値です。これらの値は、テキスト、数値、または論理値です。大文字と小文字のテキストは同じです。
Col_index_num一致する値を返す必要があるtable_arrayの列番号。 col_index_num が 1 の場合は table_array の最初の列の値が返され、 col_index_num が 2 の場合は table_array の 2 番目の列の値が返される式です。 col_index_numが次の場合:
1より小さい場合、VLOOKUPは#VALUEを返します!違い。 table_arrayの列数より大きい場合、VLOOKUPは#REFを返します!違い。
Range_lookup VLOOKUP が正確な一致またはおおよその一致を見つけるかどうかを指定する論理値です。
ファイル1:
1GR_P1:001PI
:040VG_L1
:001PO_L3
1JPI_P1:001PO_L1
1JPI_P1:001PO_L2
ファイル2:
1JPI_P1:001PO_L1 1401UC
1JPI_P1:001PO_L2 1401UC
1HIK_P2:001ER 1402UC
1GR_P1:001PI 1402UC
出力ファイル3:
1GR_P1:001PI 1402UC
:040VG_L1 NA
:001PO_L3 NA
1JPI_P1:001PO_L1 1401UC
1JPI_P1:001PO_L2 1401UC
答え1
vlookup
Unixの汎用関数などの操作を実行できる汎用関数はありません。代わりに、よりカスタマイズされたアプローチで問題に対するソリューションを構築するための「ブリック」を提供します。これらの「レンガ」はgrep
、、awk
などsed
のツールです。
これらのツールのいずれかをawk
次のように使用できます。
vlookup.awk
FNR==NR{
a[$1]=$2
next
}
{ if ($1 in a) {print $1, a[$1]} else {print $1, "NA"} }
はい
$ awk -f vlookup.awk file2 file1
1GR_P1:001PI 1GR_P1:001PI
:040VG_L1 NA
:001PO_L3 NA
1JPI_P1:001PO_L1 1JPI_P1:001PO_L1
1JPI_P1:001PO_L2 1JPI_P1:001PO_L2
次のcolumn
コマンドを使用して出力をクリーンアップできます。
$ awk -f vlookup.awk file2 file1 | column -t
1GR_P1:001PI 1GR_P1:001PI
:040VG_L1 NA
:001PO_L3 NA
1JPI_P1:001PO_L1 1JPI_P1:001PO_L1
1JPI_P1:001PO_L2 1JPI_P1:001PO_L2
詳細
上記のawk
スクリプトは値をキーとして使用して、インデックス付き配列にfile2のすべての内容を入れます。
a[$1]=$1
file2
配列を読んa
だ後、一度file1
に1行ずつ調べて決定を下します。file1
列 1 の値が配列にある場合、a
列 2 の対応する値はfile2
列 1 と一緒に印刷されます。file1
存在しない場合は、「NA」メッセージが印刷されます。
答え2
POSIXコマンドは、次のjoin(1)
ような操作を行います。VLOOKUP()
入力ファイルは、結合する列にすでにソートされている必要があります。。
$ sort file1 > sfile1
$ sort file2 > sfile2
$ join -a1 sfile1 sfile2
1GR_P1:001PI 1402UC
1JPI_P1:001PO_L1 1401UC
1JPI_P1:001PO_L2 1401UC
:001PO_L3
:040VG_L1
残念ながら、あなたの例には1つの列しか含まれていないので、join
これがどのように機能するかを実際に説明しません。file1
目的の出力を正確に取得するには、awk
他の人が提案したように、連想配列を使用して単純なスクリプトを作成できます。
答え3
提供した特定のデータ例では、次のことが機能します。File2
フィールド1でインデックス付けされた配列にフィールド2をロードします。File1
その後、ループと配列の一致またはNA
印刷
awk 'NR == FNR{a[$1] = $2;next}; {print $1, $1 in a?a[$1]: "NA"}' File2 File1
答え4
awkとredis(非常に高速なオープンソースのNoSQL Key-Valueストア)を混ぜてみてください。http://redis.io詳細はこちら)。
awkを使用して2つのファイルを解析してredisコマンドを生成します。
2つのawkスクリプトの結果をbashにパイプして実行します。それだけです:-)
ステップバイステップ:
次のように "File2" を解析して redis "SET" ステートメントを生成します。
awk '{print "redis-cli SET KEY:" $1 " \"" $2"\""}' File2
redis-cli SET KEY:1JPI_P1:001PO_L1 "1401UC"
redis-cli SET KEY:1JPI_P1:001PO_L2 "1401UC"
redis-cli SET KEY:1HIK_P2:001ER "1402UC"
redis-cli SET KEY:1GR_P1:001PI "1402UC"
生成されたredis "SET"ステートメントをbashにパイプして実行します。
awk '{print "redis-cli SET KEY:" $1 " \"" $2"\""}' File2 |\
bash
OK
OK
OK
OK
次のように "File1" を解析して redis "GET" ステートメントを生成します。
awk '{print "printf \"" $1 " \" && redis-cli GET KEY:" $1}' File1
printf "1GR_P1:001PI " && redis-cli GET KEY:1GR_P1:001PI
printf ":040VG_L1 " && redis-cli GET KEY::040VG_L1
printf ":001PO_L3 " && redis-cli GET KEY::001PO_L3
printf "1JPI_P1:001PO_L1 " && redis-cli GET KEY:1JPI_P1:001PO_L1
printf "1JPI_P1:001PO_L2 " && redis-cli GET KEY:1JPI_P1:001PO_L2
これで、上で生成されたredis "GET"ステートメントをbashにパイプしてredisを照会します。
awk '{print "printf \"" $1 " \" && redis-cli GET KEY:" $1}' File1 |\
bash
1GR_P1:001PI "1402UC"
:040VG_L1 (nil)
:001PO_L3 (nil)
1JPI_P1:001PO_L1 "1401UC"
1JPI_P1:001PO_L2 "1401UC"
redisインポートエラーを回避するには、単一のバックスラッシュを使用して文字列から二重引用符をエスケープする必要があります(slmの回答を参照)。埋め込まれた二重引用符を一重引用符に置き換えるようにこのPerlソリューションを変更するにはどうすればよいですか?)。値に二重引用符が含まれている場合は、Redisにインポートするために値を一重引用符で囲むこともできます。
ファタイ
バニー