0

I am writing a python scripts that reads the output of iperf3 client and fetches the required data in yml. Basically the script reads the output table and it has to capture the receiver's values for interval, transfer and bandwidth. To an extent the pattern matching is working, but the output is quite junky and not as expected. Please find my python script below:

import re

output = """
Connecting to host 9.10.21.01, port 5201
[  4] local 9.17.201.011 port 44466 connected to 9.10.21.01 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-2.00   sec  1.71 GBytes  7.36 Gbits/sec  264    789 KBytes
[  4]   2.00-4.00   sec  1.63 GBytes  6.99 Gbits/sec  133    865 KBytes
[  4]   4.00-5.00   sec   732 MBytes  6.14 Gbits/sec   11    826 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-5.00   sec  4.06 GBytes  6.97 Gbits/sec  408             sender
[  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec                  receiver
"""
receiver_line = re.search(r'\[\s+\d+\]\s+(.*?)\s+sec\s+(.*?)\s+(.*?)\s+receiver', output)
if receiver_line:
    interval, transfer, bandwidth = receiver_line.groups()
    output_yaml = f"Interval: {interval}\nTransfer: {transfer}\nBandwidth: {bandwidth}"
    print(output_yaml)
else:
    print("Receiver data not found in the output.")

My code seems to execute without any errors but somehow the pattern matching seems to be messed up. The output that is returned from the code is

Interval: 0.00-5.00
Transfer: 4.06 GBytes  6.97 Gbits/sec  408             sender
Bandwidth: [  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec

The expected output should be something like shown below. Is there some tweaks I need to make or is there any other approach I can try?

Interval: 0.00-5.00
Transfer: 4.05 GBytes
Bandwidth: 6.96 Gbits/sec

2 Answers2

0

Your code should work as expected if you use the following regex pattern:

import re

output = """
Connecting to host 9.10.21.01, port 5201
[  4] local 9.17.201.011 port 44466 connected to 9.10.21.01 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-2.00   sec  1.71 GBytes  7.36 Gbits/sec  264    789 KBytes
[  4]   2.00-4.00   sec  1.63 GBytes  6.99 Gbits/sec  133    865 KBytes
[  4]   4.00-5.00   sec   732 MBytes  6.14 Gbits/sec   11    826 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-5.00   sec  4.06 GBytes  6.97 Gbits/sec  408             sender
[  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec                  receiver
"""
receiver_line = re.search(r'([\d.]+-[\d.]+)\s+sec\s+([\d.]+\s+\w?Bytes)\s+([\d.]+\s+\w?bits/sec)\s+receiver', output)
if receiver_line:
    interval, transfer, bandwidth = receiver_line.groups()
    output_yaml = f"Interval: {interval}\nTransfer: {transfer}\nBandwidth: {bandwidth}"
    print(output_yaml)
else:
    print("Receiver data not found in the output.")

Alternatively since you indicated that column widths are fixed you could also iterate over lines and read out the different data fields with string indexing:

output = """
Connecting to host 9.10.21.01, port 5201
[  4] local 9.17.201.011 port 44466 connected to 9.10.21.01 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-2.00   sec  1.71 GBytes  7.36 Gbits/sec  264    789 KBytes
[  4]   2.00-4.00   sec  1.63 GBytes  6.99 Gbits/sec  133    865 KBytes
[  4]   4.00-5.00   sec   732 MBytes  6.14 Gbits/sec   11    826 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-5.00   sec  4.06 GBytes  6.97 Gbits/sec  408             sender
[  4]   0.00-5.00   sec  4.05 GBytes  6.96 Gbits/sec                  receiver
"""
for line in output.split('\n'):
    interval = line[6:18].strip()
    transfer = line[25:37]
    bandwidth = line[38:53]
    role = line[70:79].strip()
    if role == 'receiver':
        output_yaml = f"Interval: {interval}\nTransfer: {transfer}\nBandwidth: {bandwidth}"
        print(output_yaml)
        break
else:
    print("Receiver data not found in the output.")
Xukrao
  • 8,003
  • 5
  • 26
  • 52
0

Try this regex

\[\s+\d+\]\s+(.*?)\s+sec\s+(.*?Bytes)\s+(.*?sec)\s+receiver

Notice that the only differences are that Bytes (for GBytes or MBytes, or other possible Bytes) and sec (for Gbits/sec or other per sec unit) are included in the grouping for Transfer and Bandwidth.

Fanchen Bao
  • 3,310
  • 1
  • 21
  • 34