Linux
Uniq by 兩列有兩個條件
我有列的表。在第一列中,我有時間,當使用者登錄時,在第二列中,我有一個使用者名。
13:15:39 fxs1cia1qulm1lk 13:15:39 fxs1cia1qulm1lk 13:15:39 fxs1cia1qulm1lk 13:15:42 faaaa2aa11111 13:15:49 terd1sfsd11fsdf 13:15:49 terd1sfsd11fsdf 13:15:49 terd1sfsd11fsdf 13:15:59 21erdsf123sdfsdf 13:15:59 21erdsf123sdfsdf 13:15:59 21erdsf123sdfsdf 13:15:59 21erdsf123sdfsdf 13:17:50 abcasbbabadab 13:17:50 abcasbbabadab 13:17:50 abcasbbabadab 13:17:50 abcasbbabadab 13:19:19 fxs1ce1iulmla 13:19:19 fxs1ce1iulmla 13:19:19 fxs1ce1iulmla 13:20:42 faaa2a0a1111
所以,我應該怎麼做。我應該對這兩列進行 uniq 操作,如果使用者登錄的時間和使用者名相同,我應該說,該使用者已經登錄了 3 次以上。我寫了簡短的腳本:
log_file=/root/log temp_file=/root/temp temp_file2=/root/temp2 cat /dev/null > $temp_file cat /dev/null > $temp_file2 cat /dev/null > $result_file cat $log_file | awk '{print $1}' | tail -n 20 > $temp_file cat $log_file | awk '{print $5}' | tail -n 20 > $temp_file2 for i in `uniq -c $temp_file | awk '{print $1}'`; do for y in `uniq -c $temp_file2 | awk '{print $2}'`; do if [ $i -gt 3 ] && [ $y -gt 3 ]; then s=`uniq -c $temp_file2 | awk '$1 == '$i` echo "The user $s has logged more than 3 times" fi done done
請檢查一下,這個腳本是否正確?因為,在 echo 中輸出我的腳本後,我有:
The user 4 21erdsf123sdfsdf 4 abcasbbabadab has logged more than 3 times The user 4 21erdsf123sdfsdf 4 abcasbbabadab has logged more than 3 times The user 4 21erdsf123sdfsdf 4 abcasbbabadab has logged more than 3 times The user 4 21erdsf123sdfsdf 4 abcasbbabadab has logged more than 3 times
但我想要這樣的輸出:
The user 4 21erdsf123sdfsdf has logged more than 3 times The user 4 abcasbbabadab has logged more than 3 times
就這樣。我哪裡有錯誤?請幫忙。
您可以使用非常直接的方式執行此操作
awk
awk '{ users[$2]++ } END { for (user in users) if (users[user] > 1) printf "%s logged in %d times\n", user, users[user] }' < /root.log
該程序掃描 root.log 創建一個關聯數組(又名雜湊),其中包含每個使用者的計數,然後列印大於一的那些。
那麼,唯一的問題是它多次列印相同的輸出?為什麼不直接通過 uniq 進行管道傳輸?轉儲到另一個臨時文件,然後在其上執行 uniq?
如果這不是你要問的,我有一些意見:
- 在 bash/sh 中處理行分隔的數據通常比它的價值更麻煩。除非解決方案很明顯,否則請使用腳本語言,您不必一直擺弄 IFS。(如果您不知道 IFS var 是什麼,那麼我真的建議您遠離 bash/sh 以獲取行分隔數據。)
- 由於您已經在使用 awk,我敢打賭您可以將整個事情作為 awk 腳本來完成。
- 由於您關注的行是相同的,您可以執行
sort logfile | uniq -c
.- 您沒有在 uniq 之前對文件進行排序,因此如果相同的行不相鄰,則 uniq 將不起作用。例如,如果 bob 和 joe 同時登錄並且他們的日誌條目交替出現。
- 總是有 grep -c
- 閱讀排序命令,尤其是 -d、-n、-k 和 -t
更新
您是在尋求有關 shell 腳本的建議,還是在尋找一個實用的答案來回答我如何找出誰目前登錄了 3 個或更多會話?
腳本建議:
- 我很確定
$s
包含整個字元串,4 21erdsf123sdfsdf <newline> 4 abcasbbabadab
包括換行符。我不太明白為什麼。- 你為什麼這樣做
awk '{print $5}'
?我嘗試複製您的範例數據並執行它awk '{print $5}'
,我得到了一堆換行符,沒有別的。- 您是否查看過其中的內容
$temp_file
並$temp_file2
確保它們符合您的預期?- 告訴我你只想要“
tail -n 20
最近”的條目,而你不在乎有多近。這是真的?- 線是多餘的
cat /dev/null > $file
,把它們拿出來。- 替換
cat $logfile
為sort $logfile
- 縮進你的循環
基本上這個腳本不會做你想做的事,我不知道你打算如何工作,所以我不能給出更具體的建議。對不起。
實際的
- 使用@greg-tarsa 的 awk 腳本(‘向 ’e 道歉,Greg me heartie,I’aint the knowin’ o’ linkn’ t’ a user we’ a space in ‘is name)
- 您是在談論目前登錄到 unix 框嗎?你試過
who
命令嗎?EGwho | awk '{ print $1}' | sort | uniq -c | sort -d -r
還是last
命令?- 搜尋您的整體問題的答案(我如何找出誰/已經登錄了太多次),而不是更具體的問題阻止您已經嘗試實施的解決方案(Uniq by two columns with two conditions) . 如果您對練習 shell 腳本更感興趣,請以這樣的方式提出問題。