awk-1-liner to sum numbers in stdin, while printing number of occurrences of certain text along with other arbritrary text
I'm definitely interested in getting a book on awk. I've been won over, despite playing with it for little time. However, in the mean time, I have a problem I suspect I could solve exclusively with [g]awk. To demonstrate, I'll use some fdisk output. In this example, the desired end result would be something like:
Disks: 2 [240 GB total]
sda=120 GB
sdb=120 GB
Here's what I have:
fdisk -l 2>/dev/null | awk '/^Disk \/dev\/[vsh]d./ {bytes+=$5} END {print "Disks: "NR" ["; gb=bytes/1024/1024/1024; print gb" GB total]"}'
My NR apparently prints out 73.. on my laptop with two hard drives, anyway. This, I do not understand. So far, well.. I'm maybe half-w开发者_如何学JAVAay there. Any tips or succinct tutorials would be greatly appreciated!
After two major excellent answers, I ended up with the following:
echo DISKS: $(fdisk -l 2>/dev/null | awk -F/ '/^Disk \/dev\/[vsh]d.|^Disk \/dev\/xvd./{print$3}' | awk '{d++;bytes+=$4;disk[$1]=$2" "$3}END{gb=bytes/1024/1024/1024; printf gb" GB total, "d" disks\n";for (i in disk) print " "i,disk[i]}' | sed -e "s/,$/ /" -e "s/: / /")
Which gave me output like this:
DISKS: 78.3585 GB total, 2 disks
sda 80.0 GB
sdb 4110 MB
Looking forward to the day I can do that all in one awk command with no sed. :) But for now, thanks folks!
$ fdisk -l 2>/dev/null | awk '/^Disk \/dev\/[vsh]d./{d++;bytes+=$5;disk[$2]=$3$4} END {printf "Disks: "d" ["; gb=bytes/1024/1024/1024; printf gb" GB total]\n";for (i in disk) print i,disk[i]}'
Disks: 1 [93.1604 GB total]
/dev/sda: 100.0GB,
You're more than half way. The only issue is that NR
is the number of rows (so far), not the number of rows matching your expression. So just use another variable for that.
fdisk -l 2>/dev/null | awk '/^Disk \/dev\/[vsh]d./ {bytes+=$5; disks+=1} END {print "Disks: "disks" ["; gb=bytes/1024/1024/1024; print gb" GB total]"}'
That gives:
Disks: x [ yyy GB total]
To remove the newline, and add output for each drive, try:
fdisk -l 2>/dev/null | awk '/^Disk \/dev\/[vsh]d./ {cur_bytes=$5; bytes+=cur_bytes; disks+=1; gsub(/dev|:|\//, "", $2); print $2 "=" cur_bytes/1024/1024/1024 " GB";} END {printf "Disks: "disks" ["; gb=bytes/1024/1024/1024; print gb" GB total]"}'
That gives:
sda=xx GB sdb=yy GB sdc=zz GB Disks: 3 [ww GB total]
It doesn't print the header first. You could use concatenation to do that.
精彩评论