我正在嘗試創建一個簡單的 shell 腳本,顯示用戶登錄到他們的 linux 機器至少一周的次數。shell 腳本的輸出應該是這樣的:
2021-12-16
****
2021-12-15
**
2021-12-14
*******
到目前為止,我已經嘗試過這個,但它只顯示數字,但我想顯示*符號。
user="$1"
last -F | grep "${user}" | sed -E "s/${user}.*(Mon|Tue|Wed|Thu|Fri|Sat|Sun) //" | awk '{print $1"-"$2"-"$4}' | uniq -c
有什么幫助嗎?
uj5u.com熱心網友回復:
如果你有 GNU sed,你就快到了。只需將 的輸出通過管道uniq -c傳輸到這個 GNU sed 命令:
sed -En 's/^\s*(\S )\s (\S ).*/printf "\2\n%\1s" ""/e;s/ /*/g;p'
說明:在uniq -c我們的輸出中替換一行,如:
6 Dec-15-2021
經過:
printf "Dec-15-2021\n%6s" ""
我們使用eGNU sed 標志(這是一個 GNU sed 擴展,因此您需要 GNU sed)將其傳遞給 shell。輸出是:
Dec-15-2021
其中第二行包含 6 個空格。該輸出被復制回 sed 模式空間。我們通過用星星全域替換空格來完成并列印:
Dec-15-2021
******
uj5u.com熱心網友回復:
您可能希望將所有這些重構為一個簡單的 Awk 腳本,其中重復字串n次也很容易。
user="$1"
last -F |
awk -v user="$1" 'BEGIN { split("Jan:Feb:Mar:Apr:May:Jun:Jul:Aug:Sep:Oct:Nov:Dec", m, ":");
for(i=1; i<=12; i ) mon[m[i]] = sprintf("i", i) }
$1 == user { count[$8 "-" mon[$5] "-" sprintf("i", $6)] }
END { for (date in count) {
padded = sprintf("%-" count[date] "s", "*");
gsub(/ /, "*", padded);
print date, padded } }'
該BEGIN塊創建一個關聯陣列mon,將英文月份縮寫映射到月份數字。
sprintf("i", number)產生的值number用零填充到兩位數(即,如果number是單個數字,則添加前導零)。
的$1 == user。條件,其中第一場是等于我們在(你原來嘗試過這里有兩個相關的錯誤傳遞的用戶名的線條相匹配,它會尋找在該行的用戶名的任何地方,因此,如果用戶名碰巧匹配另一個欄位,它會錯誤地匹配;并且您使用的正則運算式將匹配更長欄位的子字串)。
當匹配時,我們只需更新count鍵為當前日期的關聯陣列中的值。
最后,在END塊中,我們簡單地回圈輸入值count并將它們列印出來。同樣,我們使用sprintf來生成具有合適長度的欄位。我們在這里玩一個小技巧,將空格填充到指定的寬度,因為sprintf這是開箱即用的,然后用更多星號替換空格。
您想要的輸出顯示與日期分開的一行中的星號;顯然,如果你愿意,很容易改變它,但我建議不要使用易于排序的格式grep,等等(也許然后重新格式化為你想要的最終人類可讀的形式)。
uj5u.com熱心網友回復:
一個簡單的解決方案,使用臨時檔案
#!/bin/bash
user="$1"
tempfile="/tmp/last.txt"
IFS='
'
last -F | grep "${user}" | sed -E "s/"${user}".*(Mon|Tue|Wed|Thu|Fri|Sat|Sun) //" | awk '{print $1"-"$2"-"$4}' | uniq -c > $tempfile
for LINE in $(cat $tempfile)
do
qtde=$(echo $LINE | awk '{print $1'})
data=$(echo $LINE | awk '{print $2'})
echo -e "$data "
for ((i=1; i<=qtde; i ))
do
echo -e "*\c"
done
echo -e "\n"
done
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/383723.html
下一篇:在帶路徑的檔案名前添加test_
