Linux

Uniq by 兩列有兩個條件

  • January 23, 2017

我有列的表。在第一列中,我有時間,當使用者登錄時,在第二列中,我有一個使用者名。

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 $logfilesort $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 腳本更感興趣,請以這樣的方式提出問題。

引用自:https://serverfault.com/questions/827615