Unixのvlookup関数

Unixのvlookup関数

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

vlookupUnixの汎用関数などの操作を実行できる汎用関数はありません。代わりに、よりカスタマイズされたアプローチで問題に対するソリューションを構築するための「ブリック」を提供します。これらの「レンガ」は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にインポートするために値を一重引用符で囲むこともできます。

ファタイ

バニー

関連情報