我想得到一些想法。
我的情況:我的 Linux 服務器上有大量日志,它們很大,其中也有很多東西。我想只捕獲帶有時間戳的登錄名和日志中的電子郵件地址,并將它們收集到 .txt 檔案中。
示例日志:
[...]
2019-07-21 03:13:06.939 login
[things not needed between the two]
(mail=>[email protected]< method=>email< cmd=>login<)
[...]
示例輸出:
************** 2019-07-21 **************
2019-07-21 03:13:06.939 login
[email protected]
2019-07-21 06:22:19.424 login
[email protected]
2019-07-21 12:10:23.665 login
[email protected]
2019-07-21 14:26:19.068 login
[email protected]
************** 2019-07-22 **************
2019-07-22 08:01:50.157 login
[email protected]
2019-07-22 08:12:35.504 login
[email protected]
2019-07-22 09:10:35.416 login
[email protected]
為了實作這一點,我現在正在使用它:
for i in $(ls); do echo "" && printf "************** " && cat $i | head -c 10 && printf " **************\n"; while read line; do echo $line | grep "login"; echo "$line" | grep -h -o -P '(?<=mail=>).*?(?=<)'; done < $i; done >> ../logins.txt
for 回圈正在遍歷檔案,cat $i | head -c 10將獲取日期(因為這是每個日志中的第一件事),while 回圈正在逐行讀取檔案并 greps 登錄并且僅郵件地址(grep 在“mail =>" "<")。最后它輸出到 logins.txt。
雖然這正在作業,但我發現它非常非常慢,因為它正在執行很多命令。(我們在這里談論的是 2 年的日志)而且它看起來也很臟。
我真的認為有一種有效的方法可以做到這一點,但我真的不明白那會是什么。
uj5u.com熱心網友回復:
隨著awk使用-F選擇郵件帳戶:
sep='************************'
awk -v sep="$sep" -F '(mail=>|<)' '
FNR==1 { printf("%s %s %s\n", sep, substr($0,0,10), sep)}
/mail=>/ {print $2}
/login *$/ {print}
' *
當您有其他要求并想要使用回圈時,請考慮
for f in *; do
sed -nr '
1s/(.{10}).*/********* \1 **********/p;
/login *$/p;
s/.*mail=>([^<]*).*/\1/p
' "${f}"
done
uj5u.com熱心網友回復:
awk會做得很好。您可以告訴它僅在該行與特定的正則運算式匹配時才列印該行。就像是:
awk '$0~/[0-9]{4}-[0-9]{2}-[0-9]{2}|\(mail=>/{print $0}' * > output.log
更新:注意到您只需要電子郵件。在這種情況下,兩個塊就足夠了。在第二個塊中,我們按字符<或>然后從結果陣列的索引 2 中檢索電子郵件。
awk '$1~/^[0-9]{4}-[0-9]{2}-[0-9]{2}/{print $0}$1~/^\(mail=>/{split($1,a,"[<>]");print a[2]}' * > output.log
這個 awk 說:
- 如果我們正在讀取的行的第一個欄位(該欄位由 awk 的默認空格字符分隔)以格式的日期開頭
nnnn-nn-nn:$1~/^[0-9]{4}-[0-9]{2}-[0-9]{2}/ - 然后列印整行
{print $0} - 如果我們正在讀取的行的第一個欄位以字符開頭
(mail=>:$1~/^\(mail=>/ - 然后按字符
<或將第一個欄位拆分>為名為 的陣列a:split($1,a,"[<>]") - 然后列印陣列中的第三項(索引 2):
print a[2] - 對于當前目錄中的所有檔案:
* - 將輸出發送到檔案,而不是列印到命令列:
> output.log
uj5u.com熱心網友回復:
如果除了日志檔案的前 10 個字符之外沒有其他方法可以獲取日期,那么至少您可以簡化 grep 部分:
for logfile in ./*
do
printf '************** %s **************\n' $(head -c 10 "$logfile")
grep -h -o -P '.* login$|(?<=mail=>)[^<]*' "$logfile"
echo
done
但最好的辦法是用 perl/awk/ruby/python 之類的單一語言撰寫整個內容。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/406199.html
標籤:
