#! /bin/sh
wc "$@" |
awk '{ printf "%.1f characters, %.1f words per line\n", $3/$1, $2/$1 }'
Pelkästään awkillakin se sujuu, etenkin jos halutaan
muuttaa sanan määritelmää, esim.
#! /bin/awk -f
BEGIN { FS="[^-[:alpha:]]+" }
{ c += length()+1; w += NF - (!$1) - (!$NF) }
END { printf "%.1f characters, %.1f words per line\n", c/NR, w/NR }
#! /bin/awk -f
{ for (i=1; i<=length(); ++i) {
c=toupper(substr($0,i,1))
if (c ~ /[[:alpha:]]/ ) {
n[c]++
total++
}
}
}
END { for (c in n) printf "%c %.2f%%\n", c, n[c]/total*100 | "sort" }
#! /bin/sh
FS=$1 ; shift
awk -F"$FS" 'NF { t += NF-1 } END { print t }' "$@"
#! /bin/sh
awk '
BEGIN { FS="[^-[:alpha:]]+" }
{ for (i=0; ++i<=NF;) if ($i) { n[$i]++; total++ } }
END {
for (i in n)
printf "%s %d %.3f%%\n",i,n[i],n[i]/total*100 }
' | sort -k2,2n | tail
#! /bin/sh
last "$@" |
awk '
$1 !~ /^([a-z]|$)|reboot|date/ && $2 !~ "begins" {
for (i=1; $++i !~ /Mon|Tue|Wed|Thu|Fri|Sat|Sun/ ;)
;
date=$(i+2) " " $(i+3)
if (olddate && date != olddate) {
print olddate ":", total
total=0
}
olddate=date
++total
}
END { print olddate ":", total }'
#! /bin/sh
last "$@" |
awk '
$1 !~ /^[^a-z]|reboot|date/ && $2 != "begins" {
for (i=1; $++i !~ /Mon|Tue|Wed|Thu|Fri|Sat|Sun/ ;)
;
month=$(i+2)
if (oldmonth && month != oldmonth) {
print oldmonth ":",total
total=0
}
oldmonth=month
total++
}
END { print oldmonth ":" , total }'
#! /bin/sh
last "$@" |
awk '
/^$/ { exit }
$1 !~ /^(reboot|date)$/ { t[$1]++ }
END { for (u in t) print u,t[u] }'
#! /bin/sh
# average number of different users logging in on each weekday
# assuming there's at least one login per day
last "$@" |
awk '
!NF { exit }
{ for (i=1; $++i !~ /Mon|Tue|Wed|Thu|Fri|Sat|Sun/ && i<=NF;)
;
date=$(i+1) $(i+2)
if (date != olddate) {
if (wday) {
for (u in users) {
delete users[u]
++daily[wday]
}
++count[wday]
}
olddate=date
wday=$i
}
}
$1 !~ /^(reboot|date)$/ { users[$1]=1 }
END {
++count[wday]
for (d in daily)
printf "%s: %d total in %d dates, %.2f average\n",
d, daily[d], count[d], daily[d]/count[d]
}'
Jos välipäivät (ilman yhtään loginia) halutaan laskea, tehtävä on olennaisesti vaikeampi. Seuraava versio toimii kunhan joka viikko on ainakin yksi login:
#! /bin/sh
# average number of different users logging in on each weekday
# assuming there's at least one login _every week_.
last "$@" |
awk '
BEGIN {
prevday["Mon"]="Sun"
prevday["Tue"]="Mon"
prevday["Wed"]="Tue"
prevday["Thu"]="Wed"
prevday["Fri"]="Thu"
prevday["Sat"]="Fri"
prevday["Sun"]="Sat"
}
! NF { exit }
{
for (i=1; $++i !~ /Mon|Tue|Wed|Thu|Fri|Sat|Sun/ ;)
;
date=$(i+1) $(i+2)
if (date != olddate) {
if (wday) {
for (u in users) {
delete users[u]
++daily[wday]
}
++count[wday]
while ($i != prevday[wday]) {
wday=prevday[wday]
count[wday]++
}
}
olddate=date
wday=$i
}
}
$1 !~ /^(reboot|date)$/ { users[$1]=1 }
END {
++count[wday]
for (d in daily)
printf "%s: %d total in %d dates, %.2f average\n",
d,daily[d],count[d],daily[d]/count[d]
}'
Periaatteessa samalla logiikalla saisi käsitellyksi
alle kuukauden tai alle vuodenkin loginittomat jaksot
(yli 5 vuoden katkoja ei teoriassakaan enää voi aina
hoitaa oikein).
#!/bin/sh
sort -t: -k3n /etc/passwd |
awk -F: -v limit=${1:-499} '
BEGIN { last=limit }
{ if ($3 <= limit) next
if ($3 > last+1) { exit }
last=$3
}
END { print last+1 }'
tai
#!/bin/awk -f
BEGIN {
FS=":"
limit=499
if (ARGV[1]) limit=ARGV[1]
ARGC=1
last=limit
while ("sort -t: -k3n /etc/passwd" | getline) {
if ($3 <= limit) continue
if ($3 > last+1) { exit }
last=$3
}
}
END { print last+1 }
#! /bin/awk -f
{ for (i=0; ++i <= NF;) t[NR,i]=$i }
END {
for (i=0; ++i <= NF;) {
for (j=0; ++j <= NR;) printf " %d",t[j,i]
printf "\n"
}
}
#! /bin/awk -f
$1 == "%DEFINE" {
name=$2
sub("^" $1 "[ \t]*" $2 "[ \t]*","")
values[name]=$0
next
}
{ for (macro in values) gsub("%" macro "%",values[macro])
print
}
#! /bin/awk -f
BEGIN{
if (ARGV[1] !~ /^([0-9]+\.)?([0-9]+\.)?([0-9]+)(\.[0-9]+-[0-9]+)?$/) {
printf "invalid argument"
exit 1
}
n=split(ARGV[1],a,"[.]")
if (split(a[n],r,"-")<2) { r[1]=25; r[2]=255; ++n }
if (n==2) { Cnet="130.234." a[1] }
else if (n==3) { Cnet="130." a[1] "." a[2] }
else { Cnet=a[1] "." a[2] "." a[3] }
ARGV[1]=""
if (!ARGV[2]) ARGV[1]="-"
}
/^;/{ next }
/^[a-zA-Z]/{ hostname = $1 }
/^[ \t]/{ $0 = hostname " " $0 }
$2 == "IN" && $3 =="A" { used[$4]=1 }
END{
for (c=r[1]; c<=r[2]; ++c) {
ip=Cnet "." c
if (!(ip in used)) print ip
}
}
tai
#! /bin/sh
case $1 in
[!0-9]*) Cnet=130.234.164; Range=25-128;;
*.*.*.*) Cnet=${1%.*}; Range=${1##*.} ; shift ;;
*.*.*) Cnet=$1; Range=25-128 ; shift;;
*.*) Cnet=130.234.${1%.*}; Range=${1#*.} ; shift;;
?*) Cnet=130.234.$1; Range=25-128 ;shift ;;
*) Cnet=130.234.164; Range=25-128 ;;
esac
Start=${Range%-*}
Stop=${Range#*-}
awk -v Cnet=$Cnet '
/^;/{ next }
/^[a-zA-Z]/{ hostname = $1 }
/^[ \t]/{ $0 = hostname " " $0 }
$2 $3 == "INA" { print $4 }' "${@:-it.hosts}" >usedIPs
awk 'BEGIN{ for (c='$Start'; c<='$Stop'; ++c) print "'$Cnet'." c }' |
grep -vxf usedIPs
#! /bin/awk -f
$1 == "KEY" { keys[$2]=$3 }
keys[$1] {
for (i=0; ++i<=keys[$1] ;) printf "%s ",$i
printf "\n" }