2016-11-28 37 views
4

有這樣一個典型的問題:給出一個值列表,檢查它們是否存在於一個數組中。如何將變量切片爲數組索引?

awk,關鍵val in array也工作得很好。因此,典型的想法是將所有數據存儲在一個數組中,然後繼續進行檢查。例如,這將打印,其中第一列的值是存在於陣列中的所有行:

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

然而,可以初始化所述陣列需要一些時間,因爲val in array檢查該索引val是在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[]names["hello"]names["adieu"]與空值。這樣一來,我們已經準備好爲
  • $1 in names來檢查,如果第一列是names[]任何指數。

正如你看到的,我們切到一個臨時變量v稍後初始化最終的和有用的變量names[]

有沒有初始化數組,而不是設置一起來,然後用它的值作爲最終的索引的索引任何更快的方法?

回答

3

不,這是最快的(由於哈希查找)和最強大的(由於字符串比較)的方式做你想做的。

此:

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

在啓動時發生一次,並會採取接近沒有時間,而這一點:

$1 in array_var 

這對於輸入的每一行發生一次(因此是需要的地方以獲得最佳性能)是散列查找,因此是將字符串值與一組字符串進行比較的最快方法。

2

不是數組解決方案,但一個技巧是使用模式匹配。消除部分匹配將搜索和數組值與分隔符一起打包。對於你的榜樣,

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

正則表達式比較是不是哈希查找所以因人而異,性能這樣做慢,那麼你必須處理您的數據產生錯誤匹配的正則表達式元字符。 –