2016-11-28 17 views
4

この典型的な問題があります:値のリストが与えられている場合、それらが配列内に存在するかどうかを確認します。変数を配列インデックスにスライスする方法は?

awkでは、トリックval in arrayはかなりうまくいきます。したがって、一般的な考え方は、すべてのデータを配列に格納し、チェックを続けることです。

awk 'BEGIN {<<initialize the array>>} $1 in array_var' file 

しかし、それはインデックスvalarrayであれば、アレイはval in arrayチェックするため、いくつかの時間がかかる初期化し、何されている:例えば、これは最初の列の値が配列中に存在するすべての行を印刷します我々は通常arrayに格納されている値のセットです。

これは、コマンドラインから値を提供するときに関連性が高くなります。これらの値は、配列のインデックスとして含める要素です。例えば、(私の好奇心を誘発しrecent answer of mine、に基づいて)この基本的な例では:

$ cat file 
hello 23 
bye 45 
adieu 99 
$ awk -v values="hello adieu" 'BEGIN {split(values,v); for (i in v) names[v[i]]} $1 in names' file 
hello 23 
adieu 99 
  • split(values,v)スライス可変valuesアレイv[1]="hello"; v[2]="adieu"
  • for (i in v) names[v[i]]names["hello"]names["adieu"]とで別のアレイnames[]を初期化するに空の値。このようにして、
  • $1 in namesの準備が整いました。最初の列がnames[]のインデックスのいずれかであるかどうかを確認します。

ご覧のとおり、vの変数にスライスして、最終的に有用な変数names[]を初期化します。

アレイのインデックスを初期化し、その値を最終的なもののインデックスとして使用する代わりに、インデックスを初期化する方法はありますか?

答えて

3

はありません、それはあなたが望むものを行う方法(による文字列の比較に)最速(ルックアップをハッシュによる)と最も堅牢です。

この:

BEGIN{split(values,v); for (i in v) names[v[i]]} 

は、起動時に一度起こると、このしばらく時間がないに近いかかります。

$1 in array_var 

ので、入力のライン毎に一度起こる(および必要な場所であります最適なパフォーマンスを得るために)はハッシュルックアップなので、文字列の値と文字列のセットを比較する最も速い方法です。

2

アレイソリューションではありませんが、パターンマッチングを使用するのが1つです。部分一致を除去するには、検索と配列の値を区切り文字で囲みます。あなた例えば、

$ awk -v values="hello adieu" 'FS values FS ~ FS $1 FS' file 
hello 23 
adieu 99 
+1

正規表現の比較はそれをやって、パフォーマンスとYMMVので、ハッシュのルックアップよりも遅いと、あなたはその後、偽の一致を作成してデータ内の正規表現のメタ文字に対処する必要があると思います。 –

関連する問題