answered
2015-11-21 13:30:10 +0100
Důvod a vysvětlení chyby v Tvém řešení už zmínili ostatní, rád ukážů řešení mé:
awk '!/\[error\]/{a[$6]++}END{max=0;for(i in a){if(a[i]>max)max=a[i]} print max}' apache.log
Když jsem si zadání přečetl, hned mě napadlo awk. Jak je vidět, jde to hezky napsat pomocí jednoho awk, celkem jednoduše a snad i srozumitelně. A je to i rychlejší než 2x sort. Poprvé sort potřebuji, ale podruhé mi stačí jen najít maximální hodnotu (a kvůli tomu nepotřebuji vše řadit - O(n) vs. O(n log n))
Pár lidí ale namítalo, že jsme awk ještě nebrali. Proto se báli i obyčejného
awk '{print $1}'
Které ušetřilo spoustu trápení a je mnohem mocnější než cut. Cut (bohužel) nezvládá více oddělovačů jdoucích po sobě.
Viz rozdíl
echo " 3" | cut -d\ -f1
echo " 3" | awk '{print $1}'
Na odstranění přebytečných mezer bez awk máme více možností. Výše zmíněný sed, nebo třeba grep -o
tr -s ' ' <apache.log | grep -v '\[error\]' | cut -d\ -f6 | sort | uniq -c | sort -nr | head -1 | grep -o '[0-9]*' | head -1
Někdo vtipně neodstraňoval mezery, ale pomocí echo je tam naopak přidával :-D Takže v řešení se fantazii meze nekladou.
Ještě jeden na Babicu: Když nemáme sed, awk ani grep, tak tam dáme tr: (POZOR, NEFUNGUJE!)
tr -s ' ' <apache.log | grep -v '\[error\]' | cut -d\ -f6 | sort | uniq -c | sort -nr | head -1 | tr -s ' ' | cut -d\ -f-2 | tr -d ' '
čas:
Fray
[email protected]:~$ wc -l <apache.log
1000797
[email protected]:~$ du -sh apache.log
140M apache.log
[email protected]:~$ time awk '!/\[error\]/{a[$6]++}END{max=0;for(i in a){if(a[i]>max)max=a[i]} print max}' apache.log
375375
real 1m34.088s
user 1m33.637s
sys 0m0.405s
[email protected]:~$ time tr -s ' ' <apache.log | grep -v '\[error\]' | cut -d\ -f6 | sort | uniq -c | sort -nr | head -1 | ggrep -o '[0-9]*' | head -1
375375
real 1m15.272s
user 1m38.935s
sys 0m2.716s
Webdev
[email protected] ~ $ ll apache.log
-rw-r----- 1 bartimar users 145M Nov 21 20:52 apache.log
[email protected] ~ $ time awk '!/\[error\]/{a[$6]++}END{max=0;for(i in a){if(a[i]>max)max=a[i]} print max}' apache.log
375375
real 0m4.094s
user 0m1.820s
sys 0m0.756s
[email protected] ~ $ time tr -s ' ' <apache.log | grep -v '\[error\]' | cut -d\ -f6 | sort | uniq -c | sort -nr | head -1 | grep -o '[0-9]*' | head -1
375375
real 0m12.529s
user 0m11.272s
sys 0m7.916s
btw:
VojtechMyslivec ( 2015-11-17 22:38:13 +0100 )editsort -t'.' -k1,4n
nedela to, co bys asi chtel. Nicmene to se v teto uloze netestuje. Staci ti "nejak" seradit IP adresy, aby se stejne dostaly k sobe, aby je mohluniq
spocitat.Cislo, ktere obsahuje 3 oddelovace (
.
) asi neexistuje. Pokud bys chtel ciselne seradit IP adresu, musis pouzit-n -k1,1 -k2,2 ...
-- jinymi slovy vypsat vsechny key, podle kterych chces radit.btw2: za trapeni kocky buh zabije kotatko ;]