Updating values onto an ASCII art without changing the format

Question:

I am exploring ways on bash as well as on Python to print out values onto an ASCII art for improving the readability.

The one difficulty is to update values without changing the format of the art.

The ascii art looks something like this:

========================================================
|               |    |          |    |                 |
|               |    |          |    |                 |
|      CPU      |    |   GPU    |    |      HDD        |
|               |    |          |    |                 |
|               |    |          |    |                 |
| ${CPU_W}W     |    |          |    |                 |
| ${CPU_Freq}MHz|    |          |    |Avail Mem${size}G|
|               |    |${GPU_W}W |    | Used Mem${size}G|
|               |    |${GPU}Mhz |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
========================================================

So far, I was able to prevent the format from changing on Bash. But doing this, is not allowing me to change the values.

 cat << "EOF"
========================================================
|               |    |          |    |                 |
|               |    |          |    |                 |
|      CPU      |    |   GPU    |    |      HDD        |
|               |    |          |    |                 |
|               |    |          |    |                 |
|    ${CPU_W}W  |    |          |    |                 |
| ${CPU_Freq}MHz|    |          |    |Avail Mem${size}G|
|               |    |${GPU_W}W |    | Used Mem${size}G|
|               |    |${GPU}Mhz |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
========================================================

EOF

Without cat << "EOF" ...ascii art.... EOF, I can update the values but the format keeps changing .

Is there anyway to keep the same format even with the values changing? Thanks in advance.

Asked By: hari9602

||

Answers:

In python, you can use the format and str.ljust method.

 format(value[, format_spec])

Convert a value to a “formatted” representation, as controlled by format_spec. The interpretation of format_spec will depend on the type of the value argument; however, there is a standard formatting syntax that is used by most built-in types: Format Specification Mini-Language.

It depends on what you want the notation to be (e.g how many zeros, ecc…).

here is an example:

>>> characters = 10
>>> format(32,".2E").zfill(characters)
'003.20E+01'
>>> #first number is the minimum number of characters
>>> format(32,"{0}.2E".format(characters))
'  3.20E+01'

or, with fstrings:

>>> f"{32:.2E}"
'3.20E+01'

Example on how to use it in ascii art:

>>> def create_ascii_art(CPU_W,CPU_freq,GPU_W,
...                      GPU,Free_Mem,Used_Mem):
...    CPU_W,CPU_freq,GPU_W,GPU,Free_Mem,Used_Mem = map(float,(CPU_W,CPU_freq,GPU_W,GPU,Free_Mem,Used_Mem))
... return f'''
...========================================================
...|               |    |          |    |                 |
...|               |    |          |    |                 |
...|      CPU      |    |   GPU    |    |      HDD        |
...|               |    |          |    |                 |
...|               |    |          |    |                 |
...|{CPU_W:12.2E}W  |    |          |    |                 |
...|{CPU_freq:12.2E}MHz|    |          |    |Avail Mem{Free_Mem:7.3}G|
...|               |    |{GPU_W:8.2E}W |    | Used Mem{Used_Mem:7.3}G|
...|               |    |{GPU:6.0E}Mhz |    |                 |
...|               |    |          |    |                 |
...|               |    |          |    |                 |
...|               |    |          |    |                 |
...|               |    |          |    |                 |
...========================================================'''
>>> print(create_ascii_art(1,1,1,1,1,1))

output:

========================================================
|               |    |          |    |                 |
|               |    |          |    |                 |
|      CPU      |    |   GPU    |    |      HDD        |
|               |    |          |    |                 |
|               |    |          |    |                 |
|    1.00E+00W  |    |          |    |                 |
|    1.00E+00MHz|    |          |    |Avail Mem    1.0G|
|               |    |1.00E+00W |    | Used Mem    1.0G|
|               |    | 1E+00Mhz |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
========================================================
Answered By: XxJames07-

I’m not exactly sure what you’re trying to achieve… so?

f = """
========================================================
|               |    |          |    |                 |
|               |    |          |    |                 |
|      CPU      |    |   GPU    |    |      HDD        |
|               |    |          |    |                 |
|               |    |          |    |                 |
|{cpuW:>15}|    |          |    |                 |
|{cpuF:>15}|    |          |    |Avail Mem{ramA:>8}|
|               |    |{gpuW:>10}|    | Used Mem{ramU:>8}|
|               |    |{gpuF:>10}|    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
========================================================
"""

def main():
    cpuW = 12.2
    cpuF = 2354
    gpuW = 15.2
    gpuF = 789
    ramA = 16.1
    ramU = 12.2
    d = {
        'cpuW': f'{cpuW:.1f} W ',
        'cpuF': f'{cpuF:d} MHz ',
        'gpuW': f'{gpuW:.1f} W ',
        'gpuF': f'{gpuF:d} MHz ',
        'ramA': f' {ramA:.1f} GB',
        'ramU': f' {ramU:.1f} GB',
    }
    out = f.format_map(d)
    print(out)

if __name__ == '__main__':
    main()

Output is:

========================================================
|               |    |          |    |                 |
|               |    |          |    |                 |
|      CPU      |    |   GPU    |    |      HDD        |
|               |    |          |    |                 |
|               |    |          |    |                 |
|        12.2 W |    |          |    |                 |
|      2354 MHz |    |          |    |Avail Mem 16.1 GB|
|               |    |   15.2 W |    | Used Mem 12.2 GB|
|               |    |  789 MHz |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
========================================================
Answered By: phibel

The "format" does not change; the display width of the strings in the here document depends on the values of the variables. You’ll want to make sure the values are padded to the expected width (or truncated, if necessary).

A slightly tortured way to accomplish this is to pad the actual values:

#!/bin/bash

:

printf -v CPU_W '%8s' "$CPU_W"
printf -v CPU_Freq '%11s' "$CPU_Freq"
printf -v GPU_W '%8s' "$GPU_W"
printf -v GPU '%6s' "$GPU"
printf -v size '%7s' "$size"

cat <<EOF
========================================================
|               |    |          |    |                 |
|               |    |          |    |                 |
|      CPU      |    |   GPU    |    |      HDD        |
|               |    |          |    |                 |
|               |    |          |    |                 |
|    ${CPU_W}W  |    |          |    |                 |
| ${CPU_Freq}MHz|    |          |    |Avail Mem${size}G|
|               |    |${GPU_W}W |    | Used Mem${size}G|
|               |    |${GPU}Mhz |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
|               |    |          |    |                 |
========================================================

EOF

Probably a better solution altogether is to use printf directly to format the output. (Personally, I would perceive a notable reduction in my blood pressure if you removed at least half of the repetitive "ASCII art", which would somewhat tidy up the necessary code, too.)

We can’t know what values these variables contain; if they are integers, maybe experiment with i instead of s for the printf format code, or correspondingly f or perhaps g for floating-point values.

If you need truncation, try %8.8 instead of %8, etc.

An altogether nicer approach is to use a library for producing this format. I can’t recommend any particular one for Bash; for Python, look at tabulate.

Answered By: tripleee
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.