Parsing YABS output with awk

mikhomikho AdministratorOG Bash Me Gently
edited August 21 in Blog
5 min read

You know the thread. Someone's shopping for a cheap VPS, they ask "which is faster, Contabo or RackNerd or the new Hetzner box," and six people paste their full yabs.sh output in reply. Each one is forty-plus lines of system info, fio disk tables, iperf3 network results, and a Geekbench 6 score buried near the bottom. Scrolling through five of these to compare single-core numbers is how you lose twenty minutes you didn't mean to spend.

Here's what actually gets pasted, trimmed to the parts that matter:

### Contabo VPS S SSD (Nuremberg)

fio Disk Speed Tests (Mixed R/W 50/50) (Partition /):
---------------------------------
Block Size | 4k            (IOPS) | 64k           (IOPS)
  ------   | ---            ----  | ----           ----
Read       | 61.14 MB/s   (15.2k) | 214.30 MB/s   (3.3k)
Write      | 61.35 MB/s   (15.3k) | 216.02 MB/s   (3.3k)
...

Geekbench 6 Benchmark Test:
---------------------------------
Test            | Value
                |
Single Core     | 812
Multi Core      | 2431
Full Test       | https://browser.geekbench.com/v6/cpu/7710214

That ### Contabo VPS S SSD (Nuremberg) header isn't from YABS, it's whatever the poster typed above their paste to say which box this is. Everything below it is the script's own formatting, and it's consistent enough between runs that awk can chew through it without much fuss.

The quick version: just the Geekbench numbers

If all you want is single-core and multi-core scores lined up so you can eyeball which box is actually faster:

awk -F'|' '
/^### /{p=$0; sub(/^### /,"",p)}
$1~/^Single Core[ \t]*$/{s=$2; gsub(/^[ \t]+|[ \t]+$/,"",s)}
$1~/^Multi Core[ \t]*$/{m=$2; gsub(/^[ \t]+|[ \t]+$/,"",m); printf "%-30s single=%-6s multi=%s\n", p, s, m}
' pasted-results.txt

Run against three pasted YABS blocks, that produces:

Contabo VPS S SSD (Nuremberg)  single=812    multi=2431
RackNerd VPS (Los Angeles)     single=1189   multi=1972
Hetzner CX22 (Falkenstein)     single=1204   multi=2298

The trick is the -F'|' field separator. YABS lays its tables out with pipes, so once you split on those, Single Core | 812 becomes two fields: $1 is the label with trailing spaces, $2 is the value with a leading space. The gsub calls strip that whitespace so you're left with a bare number. The header pattern (/^### /) resets which provider name gets attached to the next score it finds, so as long as your pasted results keep that header convention, each row in the output lines up with the right box.

Adding disk speed to the comparison

Geekbench alone doesn't tell you if the disk is going to choke under real load, and on a lot of $3-a-month VPS plans, the disk is the actual bottleneck, not the CPU. The fio section has the same pipe-delimited shape, just with more noise around it: the 4k block numbers come with IOPS counts in parentheses that you don't want mixed into your speed comparison.

BEGIN {
    FS = "|"
    printf "%-28s %8s %8s %14s %14s\n", "Provider", "Single", "Multi", "4k Read", "4k Write"
}
/^### / {
    provider = $0
    sub(/^### /, "", provider)
    in4k = 0
}
/Block Size[ \t]*\| *4k/ { in4k = 1 }
/Block Size[ \t]*\| *512k/ { in4k = 0 }
in4k && $1 ~ /^Read[ \t]*$/ {
    val = $2
    match(val, /[0-9.]+ *[A-Za-z\/]+/)
    read4k = substr(val, RSTART, RLENGTH)
}
in4k && $1 ~ /^Write[ \t]*$/ {
    val = $2
    match(val, /[0-9.]+ *[A-Za-z\/]+/)
    write4k = substr(val, RSTART, RLENGTH)
}
$1 ~ /^Single Core[ \t]*$/ {
    single = $2
    gsub(/^[ \t]+|[ \t]+$/, "", single)
}
$1 ~ /^Multi Core[ \t]*$/ {
    multi = $2
    gsub(/^[ \t]+|[ \t]+$/, "", multi)
    printf "%-28s %8s %8s %14s %14s\n", provider, single, multi, read4k, write4k
}

Save that as parse-yabs.awk and run awk -f parse-yabs.awk pasted-results.txt. Against the same three-provider paste:

Provider                       Single    Multi        4k Read       4k Write
Contabo VPS S SSD (Nuremberg)      812     2431     61.14 MB/s     61.35 MB/s
RackNerd VPS (Los Angeles)       1189     1972    143.67 MB/s    144.13 MB/s
Hetzner CX22 (Falkenstein)       1204     2298    268.90 MB/s    270.02 MB/s

Now the whole comparison is one glance instead of three separate walls of text. Contabo's CPU numbers look fine on paper, but that 61 MB/s on 4k random writes is the kind of thing that explains why a database on that box feels sluggish even when the benchmark score says it shouldn't.

LowEndSpirit - VPS Hosting and tech forum

The in4k flag is doing the real work here. YABS runs the fio test at four block sizes (4k, 64k, 512k, 1m) in the same table, and the Read/Write labels repeat for each one. Without tracking which block-size section you're currently inside, the script would just grab whichever Read/Write pair it saw last, which on a four-block table is the 1m numbers, not the 4k ones you probably care about for a general-purpose VPS. Flip the two Block Size patterns near the top if you'd rather track 512k or 1m instead.

Where this breaks

YABS output format has changed between versions before, and it'll probably change again. If a future release of yabs.sh reformats the fio table or renames "Single Core" to something else, this script silently produces blank columns instead of erroring, which is worse than a crash because you might not notice. Check the output against the raw paste the first time you run it against a new YABS version, after that it's fire and forget for as many providers as people keep dropping into the thread.

The other limitation: this assumes everyone pastes their result under a ### provider name header. Not everyone does. If someone just pastes raw yabs.sh output with no label, the script will still grab their numbers, just under whatever the previous header was, which is wrong. Worth a note at the top of your comparison thread asking people to label their pastes, it saves you from a script that fails quietly.

“Technology is best when it brings people together.” – Matt Mullenweg

Sign In or Register to comment.