Uniq 由兩個條件的兩個欄位組成

Uniq 由兩個條件的兩個欄位組成

我有帶列的表格。在第一列中,我有時間,當使用者登入時,在第二列中,我有使用者名稱。

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

就這樣。我哪裡有錯誤?請幫忙。

答案1

您可以透過非常簡單的方式執行此操作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,建立一個包含每個使用者計數的關聯數組(也稱為雜湊),然後列印大於 1 的陣列。

答案2

那麼,唯一的問題是它多次列印相同的輸出?為什麼不直接透過 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,我不知道'o'鏈接't'用戶,我們'是名字中的空格)
  • 你是在談論目前登入unix 盒子的情況嗎?你嘗試過who命令嗎? EGwho | awk '{ print $1}' | sort | uniq -c | sort -d -r還是last指令?
  • 搜尋您的整體問題的答案(我如何找出誰登入/登入次數過多),而不是阻止您已經嘗試實現的解決方案的更具體的問題(Uniq 由兩列和兩個條件) 。如果您對練習 shell 腳本更感興趣,請以這樣的方式提出您的問題。

相關內容