[英]Conditional Awk hashmap match lookup
我有2個表格文件。 一個文件包含50個鍵值的映射,僅稱為lookup_file.txt。 另一個文件具有30列和數百萬行的實際表格數據。 data.txt我想用lookup_file.txt中的值替換第二個文件的id列。 。
我怎樣才能做到這一點? 我更喜歡在bash腳本中使用awk ..此外,是否有一個hashmap數據結構我可以在bash中用於存儲50個鍵/值而不是另一個文件?
假設您的文件有逗號分隔的字段,“id列”是字段3:
awk '
BEGIN{ FS=OFS="," }
NR==FNR { map[$1] = $2; next }
{ $3 = map[$3]; print }
' lookup_file.txt data.txt
如果這些假設中的任何一個是錯誤的,請告訴我們如果修復不明顯......
編輯:如果你想避免(恕我直言可以忽略不計)NR == FNR測試性能影響,這將是使用getline時適用的每種罕見情況之一:
awk '
BEGIN{
FS=OFS=","
while ( (getline line < "lookup_file.txt") > 0 ) {
split(line,f)
map[f[1]] = f[2]
}
}
{ $3 = map[$3]; print }
' data.txt
您可以通過bash混合使用“sort”和“join”,而不必將其寫入awk / sed,它可能更快:
key.cvs(id,name)
1,homer
2,marge
3,bart
4,lisa
5,maggie
data.cvs(姓名,動物,所有者,年齡)
snowball,dog,3,1
frosty,yeti,1,245
cujo,dog,5,4
現在,您需要首先在用戶ID列上對這兩個文件進行排序:
cat key.cvs | sort -t, -k1,1 > sorted_keys.cvs
cat data.cvs | sort -t, -k3,3 > sorted_data.cvs
現在加入2個文件:
join -1 1 -2 3 -o "2.1 2.2 1.2 2.4" -t , sorted_keys.cvs sorted_data.cvs > replaced_data.cvs
這應該產生:
snowball,dog,bart,1
frosty,yeti,homer,245
cujo,dog,maggie,4
這個:
-o "2.1 2.2 1.2 2.4"
在最終輸出中說出你想要的2個文件中的哪些列。
與其他腳本語言相比,查找和替換多個數據的速度非常快。 我還沒有直接與SED / AWK進行比較,但編寫一個包裝它的bash腳本比寫入SED / AWK(至少對我來說)要容易得多。
此外,您可以使用gnu coreutils的升級版本加快排序速度,以便您可以並行執行排序
cat data.cvs | sort --parallel=4 -t, -k3,3 > sorted_data.cvs
4是你要運行它的線程數。我建議每個機器核心2個線程通常會最大化機器,但如果它專用於此,那很好。
有幾種方法可以做到這一點。 但是如果你想要一個簡單的一個襯墊,沒有太多的驗證方式,我會選擇awk / sed解決方案。
假設如下:
文件是制表符分隔的
你正在使用bash shell
數據文件中的id位於第一列
你的文件看起來像這樣:
1 one
2 two
3 three
4 four
5 five
1 col2 col3 col4 col5
2 col2 col3 col4 col5
3 col2 col3 col4 col5
4 col2 col3 col4 col5
5 col2 col3 col4 col5
我會使用awk
和sed
來完成這個任務,如下所示:
awk '{print "sed -i s/^"$1"/"$2"/ data"}' lookup | bash
這樣做是通過每行查找並將以下內容寫入stdout
sed -is/^1/one/ data
sed -is/^2/two/ data
等等。
它接下來將每一行傳遞給shell( | bash
),它將執行sed
表達式。 -i for -i.bak
,您可能需要-i.bak
來創建備份文件。 請注意,您可以將擴展名更改為您想要的任何內容。 sed正在查找行開頭的id,如^
。 您不希望替換可能不包含id的列中的“id”。
您的輸出將如下所示:
one col2 col3 col4 col5
two col2 col3 col4 col5
three col2 col3 col4 col5
four col2 col3 col4 col5
five col2 col3 col4 col5
當然,你的id可能不是簡單的1比1,2比2等,但這可能會讓你開始朝着正確的方向前進。 我非常寬松地使用右邊的術語。
我這樣做的方法是使用awk
編寫一個awk
程序來處理更大的文件:
awk -f <(awk '
BEGIN{print " BEGIN{"}
{printf " a[\"%s\"]=\"%s\";",$1,$2}
END {print " }";
print " {$1=a[$1];print $0}"}
' lookup_file.txt
) data.txt
這假設id
列是第1列; 如果沒有,你需要改變$1
$1=a[$1]
兩個實例$1=a[$1]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.