Linux join命令快速實現(xiàn)從大文件中匹配內(nèi)容
一. 作業(yè)背景
項目中,每個月都會收集當月的用戶支付相關(guān)的信息,然后匯總到一個大csv文件中。
作業(yè)內(nèi)容需求:
- 當月的csv文件共有4000萬行數(shù)據(jù)
- 客戶提供了一個有2萬行的文本文件,每一行對應(yīng)著一個用戶的id
- 現(xiàn)在需要根據(jù)2萬個用戶id去大csv文件中進行檢索,將匹配到的數(shù)據(jù)傳給客戶。
作業(yè)環(huán)境需求:
- 大csv文件中存放在服務(wù)器上,因為含有客戶敏感信息,只能連接到linux環(huán)境上作業(yè)
- 只能使用linux命令來完成
遇到的問題
- 普通匹配需要的話,直接使用grep命令進行匹配即可
- 如果需要多次匹配的話,可以寫若干個grep命令,然后放到一個bash腳本中批量執(zhí)行
- 但是本次目標文件數(shù)據(jù)量龐大,匹配源文件和待匹配的目標文件數(shù)量龐大,通過grep命令的話,會消耗很多時間
解決方式
- 通過join的方式進行文件匹配可以極大提升匹配效率
- 需要提前對文件進行排序
二. 數(shù)據(jù)準備
準備40萬條數(shù)據(jù)
(
echo "No,姓名,auid,地址"
seq 1 400000 | awk 'BEGIN{OFS=","} {
printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1
}'
) > bigfile.csv
對生成的文件進行二次處理,得到亂序的數(shù)據(jù)
shuf:對文件按照行進行亂序處理,模擬真實的商用數(shù)據(jù)sed -i '1i 要插入的內(nèi)容':向第一行插入數(shù)據(jù)
# 對文件進行亂序處理 grep -v 姓名 bigfile.csv | shuf > shuffled.csv # 為csv文件添加表頭 sed -i '1i No,姓名,auid,地址' shuffled.csv
獲取后1千條數(shù)據(jù),然后將auid數(shù)據(jù)輸出到一個文件中,模擬客戶提供的數(shù)據(jù)。
tail -n 1000 shuffled.csv | awk -F',' '{print $3}' > auid_list.txt
使用shuf命令隨機從auid_list.txt文件中獲取1行數(shù)據(jù),然后給除了第三個字段的所有字段的前后后添加一個@符號之后,追加到shuffled.csv中,目的是為了模擬有多個auid存在的情況。
shuf -n 1 auid_list.txt:從文件中隨機獲取一條數(shù)據(jù)tee -a shuffled.csv:-a表示追加- 將數(shù)據(jù)打印到控制臺上的同時,將數(shù)據(jù)追加到
shuffled.csv中
grep $(shuf -n 1 auid_list.txt) shuffled.csv | awk -F',' '{
OFS = ","
$1 = "@" $1 "@"
$2 = "@" $2 "@"
$4 = "@" $4 "@"
print
}' | tee -a shuffled.csv
??? ???
@295178@,@user_name_000295178@,auid_000295178,@地球295178@
- 可以看到一個auid對應(yīng)著2條數(shù)據(jù)
apluser@FengYeHong-HP:0724$ grep -a auid_000295178 shuffled.csv 295178,user_name_000295178,auid_000295178,地球295178 @295178@,@user_name_000295178@,auid_000295178,@地球295178@
三. 數(shù)據(jù)匹配
3.1 文件排序
sort -k<開始列>[,<結(jié)束列>] file:指定排序的字段范圍,也就是告訴 sort 從第幾列到第幾列作為排序依據(jù)。
sort -t, -k3,3-t,:按照逗號進行分隔-k3,3:指定第3列作為排序依據(jù)
apluser@FengYeHong-HP:0724$ sort -t, -k3,3 shuffled.csv > all_info_sort.csv apluser@FengYeHong-HP:0724$ tail all_info_sort.csv 399991,user_name_000399991,auid_000399991,地球399991 399992,user_name_000399992,auid_000399992,地球399992 399993,user_name_000399993,auid_000399993,地球399993 399994,user_name_000399994,auid_000399994,地球399994 399995,user_name_000399995,auid_000399995,地球399995 399996,user_name_000399996,auid_000399996,地球399996 399997,user_name_000399997,auid_000399997,地球399997 399998,user_name_000399998,auid_000399998,地球399998 399999,user_name_000399999,auid_000399999,地球399999 400000,user_name_000400000,auid_000400000,地球400000
apluser@FengYeHong-HP:0724$ sort auid_list.txt > auid_list_sort.csv apluser@FengYeHong-HP:0724$ tail auid_list_sort.csv auid_000395846 auid_000395932 auid_000395948 auid_000396121 auid_000396465 auid_000396566 auid_000397508 auid_000398221 auid_000398744 auid_000398933
3.2 join命令匹配數(shù)據(jù)
3.2.1 正常數(shù)據(jù)匹配
-t,:指定通過逗號分割文件-1 1:指定第1個文件的第1個字段作為join條件-2 3:指定第2個文件的第3個字段作為join條件
apluser@FengYeHong-HP:0724$ wc -l auid_list_sort.csv 1000 auid_list_sort.csv apluser@FengYeHong-HP:0724$ join -t, -1 1 -2 3 auid_list_sort.csv all_info_sort.csv > result.csv apluser@FengYeHong-HP:0724$ wc -l result.csv 1001 result.csv apluser@FengYeHong-HP:0724$ grep -a auid_000295178 result.csv auid_000295178,295178,user_name_000295178,地球295178 auid_000295178,@295178@,@user_name_000295178@,@地球295178@
3.2.2!!!注意事項!!!
兩個文件進行join匹配數(shù)據(jù)的時候,第一個文件的換行符一定要是LF,不能是CRLF,否則無法join
- 可以看到,我們將第一個文件的換行符轉(zhuǎn)換為CRLF之后,進行join時,無任何匹配
- 在實際工作中,我們可能在windows環(huán)境中使用文本編輯器對第一個文件進行編輯,手動粘貼內(nèi)容,保存之后就直接帶到linux環(huán)境中使用了,大多數(shù)windows環(huán)境中的文本編輯器的換行符都是CRLF,因此會造成join命令無法匹配的情況。
apluser@FengYeHong-HP:0724$ nkf --guess auid_list_sort.csv
ASCII (LF)
apluser@FengYeHong-HP:0724$ awk '{printf "%s\r\n", $0}' auid_list_sort.csv > auid_list_CRLF_sort.csv
apluser@FengYeHong-HP:0724$
apluser@FengYeHong-HP:0724$ nkf --guess auid_list_CRLF_sort.csv
ASCII (CRLF)
apluser@FengYeHong-HP:0724$ nkf --guess all_info_sort.csv
UTF-8 (LF)
apluser@FengYeHong-HP:0724$ # ??????join之后, 無任何輸出??????
apluser@FengYeHong-HP:0724$ join -t, -1 1 -2 3 auid_list_CRLF_sort.csv all_info_sort.csv
apluser@FengYeHong-HP:0724$ # ??????join之后, 無任何輸出??????
四. 數(shù)據(jù)整理
通過join命令處理過之后的數(shù)據(jù),其指定用來join的字段會跑到第1列,破壞了原有的數(shù)據(jù)結(jié)構(gòu)
apluser@FengYeHong-HP:0724$ head result.csv auid_000000333,333,user_name_000000333,地球333 auid_000000835,835,user_name_000000835,地球835 auid_000000922,922,user_name_000000922,地球922 auid_000001206,1206,user_name_000001206,地球1206 auid_000001436,1436,user_name_000001436,地球1436 auid_000001853,1853,user_name_000001853,地球1853 auid_000001925,1925,user_name_000001925,地球1925 auid_000002146,2146,user_name_000002146,地球2146 auid_000002195,2195,user_name_000002195,地球2195 auid_000002798,2798,user_name_000002798,地球2798
可通過awk命令將指定字段的順序進行調(diào)換
awk -F',' '{
col1 = $1;
for(i=2; i<=3; i++) {
printf "%s,", $i
}
printf "%s", col1
for(i=4; i<=NF; i++) {
printf ",%s", $i
}
printf "\n"
}' result.csv > result_handle.csv
- 處理之后的效果
apluser@FengYeHong-HP:0724$ head result_handle.csv 333,user_name_000000333,auid_000000333,地球333 835,user_name_000000835,auid_000000835,地球835 922,user_name_000000922,auid_000000922,地球922 1206,user_name_000001206,auid_000001206,地球1206 1436,user_name_000001436,auid_000001436,地球1436 1853,user_name_000001853,auid_000001853,地球1853 1925,user_name_000001925,auid_000001925,地球1925 2146,user_name_000002146,auid_000002146,地球2146 2195,user_name_000002195,auid_000002195,地球2195 2798,user_name_000002798,auid_000002798,地球2798
五. 其他方式
除了join之外,awk命令也可以實現(xiàn)快速匹配的需求,只是效率沒有join那么高,不過一般也足夠用了。
- 核心思想就是讀取源文件和待匹配的目標文件
- 將源文件中的數(shù)據(jù)放到數(shù)組中,然后指定待匹配的目標文件的第3個字段是否在數(shù)組中
awk -F, 'NR==FNR{auid_list[$1]; next} $3 in auid_list' auid_list.txt shuffled.csv > result_handle_awk.csv
- 通過diff命令可以看到生成的文件一致
apluser@FengYeHong-HP:0724$ diff <(sort result_handle_awk.csv) <(sort result_handle.csv) apluser@FengYeHong-HP:0724$
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
linux中關(guān)于ftp查看不到文件列表的問題詳解
下面小編就為大家?guī)硪黄猯inux中關(guān)于ftp查看不到文件列表的問題詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11
Linux掛載linux/Windows共享目錄實現(xiàn)方式
這篇文章主要介紹了Linux掛載linux/Windows共享目錄實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-09-09
Centos下升級Python及Mongodb驅(qū)動安裝問題
查看python的版本 python -V 如果是2.7以下版本就需要升級了。這篇文章主要介紹了Centos下升級Python及Mongodb驅(qū)動安裝,需要的朋友可以參考下2019-11-11
Apache限制IP并發(fā)數(shù)和流量控制的方法
這篇文章主要介紹了Apache限制IP并發(fā)數(shù)和流量控制的方法,需要的朋友可以參考下2014-12-12

