Issue
I have a script that gets information about servers and stores it in a variable.
➜ echo $report
Hostname : or-05-arm
CheckDate: 11:47 27-10-2022
CPU Usage: [..........] 0% [0.00/2]
RAM Usage: [###.......] 31% [1.8G/5.8G]
HDD Avail: 26G
Uptime : up 19 weeks
Hostname : contabo-3
CheckDate: 14:47 27-10-2022
CPU Usage: [#####.....] 50% [3.01/6]
RAM Usage: [###.......] 30% [4.7G/15.6G]
HDD Avail: 136G
Uptime : up 1 week
Hostname : contabo-2
CheckDate: 14:47 27-10-2022
CPU Usage: [#####.....] 53% [3.16/6]
RAM Usage: [##........] 25% [3.9G/15.6G]
HDD Avail: 176G
Uptime : up 1 week
Using awk and a column, I display the contents of the report variable on the screen in three columns.
➜ echo $report | awk '{a[NR%7] = a[NR%7] (NR<=7 ? "" : ",") $0} END{for (i = 1; i <= 7; i++) print a[i%7]}' | column -t -s ','
Hostname : or-05-arm Hostname : contabo-3 Hostname : contabo-2
CheckDate: 11:47 27-10-2022 CheckDate: 14:47 27-10-2022 CheckDate: 14:47 27-10-2022
CPU Usage: [..........] 0% [0.00/2] CPU Usage: [#####.....] 50% [3.01/6] CPU Usage: [#####.....] 53% [3.16/6]
RAM Usage: [###.......] 31% [1.8G/5.8G] RAM Usage: [###.......] 30% [4.7G/15.6G] RAM Usage: [##........] 25% [3.9G/15.6G]
HDD Avail: 26G HDD Avail: 136G HDD Avail: 176G
Uptime : up 19 weeks Uptime : up 1 week Uptime : up 1 week
This works as long as no more than three servers are stored in the variable. If there are more than three servers, then the output does not fit on the screen.
How to make 3 servers appear on the screen, then three more on the next line, and so on?
Solution
Assumptions:
- each block of text contains exactly 6 lines (not counting blank lines)
- the last line of each block of text includes the string
Uptime
Uptime
does not show up in any other lines
Setup (7 blocks of data):
$ cat report.dat
Hostname : or-05-arm
CheckDate: 11:47 27-10-2022
CPU Usage: [..........] 0% [0.00/2]
RAM Usage: [###.......] 31% [1.8G/5.8G]
HDD Avail: 26G
Uptime : up 19 weeks
Hostname : contabo-3
CheckDate: 14:47 27-10-2022
CPU Usage: [#####.....] 50% [3.01/6]
RAM Usage: [###.......] 30% [4.7G/15.6G]
HDD Avail: 136G
Uptime : up 1 week
Hostname : contabo-2
CheckDate: 14:47 27-10-2022
CPU Usage: [#####.....] 53% [3.16/6]
RAM Usage: [##........] 25% [3.9G/15.6G]
HDD Avail: 176G
Uptime : up 1 week
Hostname : or-05-arm
CheckDate: 11:47 27-10-2022
CPU Usage: [..........] 0% [0.00/2]
RAM Usage: [###.......] 31% [1.8G/5.8G]
HDD Avail: 26G
Uptime : up 19 weeks
Hostname : contabo-3
CheckDate: 14:47 27-10-2022
CPU Usage: [#####.....] 50% [3.01/6]
RAM Usage: [###.......] 30% [4.7G/15.6G]
HDD Avail: 136G
Uptime : up 1 week
Hostname : contabo-2
CheckDate: 14:47 27-10-2022
CPU Usage: [#####.....] 53% [3.16/6]
RAM Usage: [##........] 25% [3.9G/15.6G]
HDD Avail: 176G
Uptime : up 1 week
Hostname : or-05-arm
CheckDate: 11:47 27-10-2022
CPU Usage: [..........] 0% [0.00/2]
RAM Usage: [###.......] 31% [1.8G/5.8G]
HDD Avail: 26G
Uptime : up 19 weeks
Adding a couple counters and a function (to print 3x blocks at a time) to OP's current awk
code:
awk '
function print_block() {
for (i = 1; i <= 7; i++)
print a[i%7]
print "," # column will convert this to a blank line
delete a # clear array
upcount=linecount=0 # reset counters
}
! NF { next } # skip blank lines
{ linecount++ }
{ a[linecount % 7] = a[linecount % 7] (linecount <= 7 ? "" : ",") $0 }
/Uptime/ { upcount++ }
upcount>=3 { print_block() } # dump array to stdout for each 3rd occurrence of "Uptime"
END { print_block() } # flush anything still in array once all input has been processed
' report.dat | column -t -s,
This generates:
Hostname : or-05-arm CheckDate: 14:47 27-10-2022 CPU Usage: [#####.....] 53% [3.16/6]
CheckDate: 11:47 27-10-2022 CPU Usage: [#####.....] 50% [3.01/6] RAM Usage: [##........] 25% [3.9G/15.6G]
CPU Usage: [..........] 0% [0.00/2] RAM Usage: [###.......] 30% [4.7G/15.6G] HDD Avail: 176G
RAM Usage: [###.......] 31% [1.8G/5.8G] HDD Avail: 136G Uptime : up 1 week
HDD Avail: 26G Uptime : up 1 week
Uptime : up 19 weeks Hostname : contabo-2
Hostname : contabo-3 CheckDate: 14:47 27-10-2022
Hostname : or-05-arm CheckDate: 14:47 27-10-2022 CPU Usage: [#####.....] 53% [3.16/6]
CheckDate: 11:47 27-10-2022 CPU Usage: [#####.....] 50% [3.01/6] RAM Usage: [##........] 25% [3.9G/15.6G]
CPU Usage: [..........] 0% [0.00/2] RAM Usage: [###.......] 30% [4.7G/15.6G] HDD Avail: 176G
RAM Usage: [###.......] 31% [1.8G/5.8G] HDD Avail: 136G Uptime : up 1 week
HDD Avail: 26G Uptime : up 1 week
Uptime : up 19 weeks Hostname : contabo-2
Hostname : contabo-3 CheckDate: 14:47 27-10-2022
Hostname : or-05-arm
CheckDate: 11:47 27-10-2022
CPU Usage: [..........] 0% [0.00/2]
RAM Usage: [###.......] 31% [1.8G/5.8G]
HDD Avail: 26G
Uptime : up 19 weeks
If OP has pre-loaded all of the data into a variable then there a couple options:
echo "${report}" | awk '... see code from above ...' | column -t -s,
# or
awk '... see code from above ...' <<< "${report}" | column -t -s,
NOTE: ${report}
must be wrapped in double quotes
Answered By - markp-fuso Answer Checked By - Mary Flores (WPSolving Volunteer)