I’ve got the following input:
03:00.0 Ethernet controller: Broadcom Corporation NetBooty BCM5111 Gigabit Ethernet (rev 59)
03:00.1 Ethernet controller: Broadcom Corporation NetBooty BCM5111 Gigabit Ethernet (rev 59)
03:00.2 Ethernet controller: Broadcom Corporation NetBooty BCM5111 Gigabit Ethernet (rev 59)
03:00.3 Ethernet controller: Broadcom Corporation NetBooty BCM5111 Gigabit Ethernet (rev 59)
04:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
04:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
05:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
05:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
06:00.0 Network controller: Intel Corporation Centrino Ultimate-N 6300 (rev 3e)
This is from lspci in linux and it obviously shows ethernet/wireless devices and their corresponding pci ids. In this case, the output shows me that the system has 1 quad-port BCM690 nic (I made that up), 2 dual-port BCM5709, and an Intel 6300 wifi controller.
I’m trying to write awk logic that could handle that (and much more verbose output on more interface-ful systems), printing a succinct summary. Proposed output format, given above input:
4 Broadcom Corporation NetBooty BCM5111 Gigabit Ethernet (rev 59) {1x4-port}
4 Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20) {2x2-port}
1 Intel Corporation Centrino Ultimate-N 6300 (rev 3e)
With my limited awk knowledge I’ve so far been only marginally successful. Following this is what I’ve got, but note I often review files containing lspci -v output from other systems, hence the extra '/Eth|Net/{if ($2 ~ /^Eth|^Net/) print}' logic to ensure I get the right thing.
awk '/Eth|Net/{if ($2 ~ /^Eth|^Net/) print}' lspci.txt |
awk -F: '{if ($2 ~ /^...0/) pci[$1$2]=$3; count[$3]++} END {for (i in pci) printf "%s %s\n", count[pci[i]], pci[i]}' |
uniq -c |
awk '{nic=""; for (i=3; i <=NF; i++) nic = nic $i " "; if ($1 == 1) printf "%s %s\n", $2, nic; if ($1 != 1) printf "%s %s {%dx%d-port}\n", $2, nic, $1, $2/$1}'
This produces the desired output, mostly, but uh… I’d love to get that down to a single awk command. Any feedback appreciated. Examples are even better. I don’t need the answer spelled out; I just need to be pointed to some examples of similar things. (If you’ve got a better tool for the job than awk, point me towards that too please.)
Throw away the first field and the first field delimiter. Use the rest of the line as an index into a counter array. At the end print the count and the index.
Here is a version that prints the port count (split out on multiple lines):
Save the slot information in an array. Discard the first field and the first delimiter. Count the interfaces. If we haven’t seen the slot before, remember it (simply referring to an array element creates it). Count the slots for that interface type.
For each interface type, get the slot count and the count for that type. Print the information. The number of ports per interface is the count of a type divided by slots occupied by that type of interface.
By the way, this double test:
can be simplified to: