# Ajouter un espace entre des chiffres et des lettres en python

**URL:** <https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202>\
**Category:** Programmation\
**Created:** [Mars 21, 2018, 5:28 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202 "2018-03-21T17:28:40Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Clochette](https://www.debian-fr.org/user_avatar/www.debian-fr.org/clochette/32/8757_2.png) [@Clochette](https://www.debian-fr.org/u/Clochette)\
**Post date:** [Mars 21, 2018, 5:28 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202/1 "2018-03-21T17:28:40Z")

</div>

Je bute sur un problème sans doute simple pour un dev …

Je cherche à remettre à jour un script python pour tirer parti du retour de la commande ‘docker stats’

Depuis plusieurs versions le formatage du retour de cette commande à changé et je me retrouve avec les unité collé à la valeur, or pour le traitement je cherche à insérer un espace entre la valeur et l’unité.

En bref j’obtiens quelque chose comme ça actuellement :

`78.21MiB`

Et je cherche à obtenir ça :

`78.21 MiB`

Pour l’instant j’ai tenté à l’aide de rstrip / lstrip mais sans succès pour insérer cet espace salvateur dans cette foutue chaine caractère 😕

`fdata=pdata[3].rstrip(string.digits+" ")`

Sachant que pdata[3] est mon résultat déjà parser dans le retour de ma commande et que j’ai besoin d’appliquer après coup encore une fonction (calcul) sur mon résultat fdata selon l’unité relevée.

N’étant pas des plus doué en Python si une bonne âme pythoniste pouvais me filer un coup de main pour régler ce souci ça m’arrangerai bien.

---

<div class="post-metadata">

**Author:** ![PengouinPdt](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pengouinpdt/32/3978_2.png) [@PengouinPdt](https://www.debian-fr.org/u/PengouinPdt)\
**Post date:** [Mars 21, 2018, 5:53 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202/2 "2018-03-21T17:53:25Z")

</div>

Un début :

```auto
fdata = pdata[3][:-3] 

```

Te supprimera les trois derniers caractères…  
Si tu veux un entier, tu es obligé de passer par un float (décimal) :

```auto
fdata = float(pdata[3][:-3])
print(f'{fdata}')
78.21
; pour l'int : 
fdata = int(float(pdata[3][:-3]))
print(f'{fdata}')
78

```

C’est un début, parce que je ne sais pas, ni si tu as besoin de garder la valeur lettrée d’octets, ni si elle peut avoir plus de trois lettres, ou moins…

Si tu veux absolument garder aussi la valeur lettrée d’octets :

```auto
NomBytes = pdata[3][-3:]

```

* * *

Sinon, pour avoir exactement ce que tu cherches :

```auto
fdata = pdata[3][:3] + " " + pdata[3][-3:]

```

C’est très basique ; on peut certainement faire mieux 😉

---

<div class="post-metadata">

**Author:** ![Clochette](https://www.debian-fr.org/user_avatar/www.debian-fr.org/clochette/32/8757_2.png) [@Clochette](https://www.debian-fr.org/u/Clochette)\
**Post date:** [Mars 21, 2018, 9:41 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202/3 "2018-03-21T21:41:13Z")

</div>

Bon pas de secret pour le script en lui même :

```auto
import subprocess
import os
import time
import string

def B(b):
    return int(float(b))

def KB(b):
    return int(float(b) * 1024)

def MB(b):
    return int(float(b) * 1024 * 1024)

def GB(b):
    return int(float(b) * 1024 * 1024 * 1024)

def TB(b):
    return int(float(b) * 1024 * 1024 * 1024 * 1024)

size_options = {
    'k':KB,
    'kB':KB,
    'KB':KB,
    'KiB':KB,
    'K':KB,
    'm':MB,
    'mB':MB,
    'MB':MB,
    'MiB':MB,
    'M':MB,
    'g':GB,
    'GB':GB,
    'GiB':GB,
    'G':GB,
    't':TB,
    'T':TB,
    'b':B,
    'B':B
}

def pcpu(data):
    pdata=data.split()
    pcpu_data=pdata[2].split('%')[0]
    return pcpu_data

def umem(data):
    pdata=data.split('/')[0].split()
    fdata=pdata[3][:-3] + " " + pdata[3][-3:]
    value = size_options[fdata.split()[2][0]](fdata.split()[0])
    return value
    #return fdata

def lmem(data):
    pdata=data.split('/')[1].split()
    value = size_options[pdata[1][0]](pdata[0])
    return value

def pmem(data):
    pdata=data.split()
    pmem_data=pdata[6].split('%')[0]
    return pmem_data

def inet(data):
    pdata=data.split('/')[1].split()
    value = size_options[pdata[0][0]](pdata[2])
    return value

def onet(data):
    pdata=data.split('/')[2].split()
    value = size_options[pdata[0][0]](pdata[0])
    return value

options = {
    'pcpu':pcpu,
    'umem':umem,
    'lmem':lmem,
    'pmem':pmem,
    'inet':inet,
    'onet':onet
}

def local_run_command(cmd,file):
    cmd = cmd + " | tee > " + file
    if os.path.isfile(file) == False:
        os.system(cmd)
    else:
        (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
        ticks=int(time.time())
        delta=ticks-mtime
        if (delta > 60):
            os.system(cmd)

    strings = open(file,"r").readlines()
    return strings

container=sys.argv[1]
key=sys.argv[2]

cmd="docker stats --no-stream=true " + container
strings = local_run_command(cmd,"/tmp/zabbix-docker-stats-"+container+".out")

print options[key](strings[1])

```

Bon nickel j’arrive à reformater ma sortie correctement me reste maintenant à finir de traiter la donnée correctement et la c’est pas gagné 😕

PS je commente la suite du recalcul afin de m’assurer de la bonne valeur de fdata :

```auto
# python /usr/local/bin/zabbix-docker-stats.py 692e07792052 umem

```

```auto
78.24 MiB

```

Par contre si je tente avec le script de retrouver la valeur renvoyé en B je me tape encore une erreur, je suppose que j’ai pas pigé comment fonctionne l’appel à la fonction **size\_options**

```auto
# python /usr/local/bin/zabbix-docker-stats.py 692e07792052 umem

```

```auto
Traceback (most recent call last):
 File "/usr/local/bin/zabbix-docker-stats.py", line 120, in <module>
   print options[key](strings[1])
 File "/usr/local/bin/zabbix-docker-stats.py", line 66, in umem
   value = size_options[fdata.split()[2][0]](fdata.split()[0])
IndexError: list index out of range

```

---

<div class="post-metadata">

**Author:** ![PengouinPdt](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pengouinpdt/32/3978_2.png) [@PengouinPdt](https://www.debian-fr.org/u/PengouinPdt)\
**Post date:** [Mars 21, 2018, 10:33 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202/4 "2018-03-21T22:33:14Z")

</div>

> [@Clochette](#):
>
> IndexError: list index out of range

Il te dit que tu cherches une clé qui n’existe pas - hors rang !

---

<div class="post-metadata">

**Author:** ![Clochette](https://www.debian-fr.org/user_avatar/www.debian-fr.org/clochette/32/8757_2.png) [@Clochette](https://www.debian-fr.org/u/Clochette)\
**Post date:** [Mars 22, 2018, 10:21 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202/5 "2018-03-22T10:21:18Z")

</div>

Bon finalement ça marche mais j’ai besoin de supprimer les lettres dans la string en passant par une regex car ma sortie n’est pas toujours composé de 3 lettres 😕

Je vais donc regarder du côté des regex en python.

---

<div class="post-metadata">

**Author:** ![anon29980398](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/a/f4b2a3/32.png) [@anon29980398](https://www.debian-fr.org/u/anon29980398)\
**Post date:** [Mars 22, 2018, 11:06 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202/6 "2018-03-22T11:06:32Z")

</div>

Bonjour

```python
>>> import re
>>> 
>>> fdata = "78.24MiB"
>>> re.sub(r"(\d+\.\d+|\d+)(\w+)", r"\1 \2", fdata)
'78.24 MiB'
>>> re.sub(r"(\d+\.\d+|\d+)(\w+)", r"\1", fdata)
'78.24'
>>> 
>>> fdata = "7824MiB"
>>> re.sub(r"(\d+\.\d+|\d+)(\w+)", r"\1", fdata)
'7824'
>>> 

```

---

<div class="post-metadata">

**Author:** ![Clochette](https://www.debian-fr.org/user_avatar/www.debian-fr.org/clochette/32/8757_2.png) [@Clochette](https://www.debian-fr.org/u/Clochette)\
**Post date:** [Mars 22, 2018, 6:53 UTC](https://www.debian-fr.org/t/ajouter-un-espace-entre-des-chiffres-et-des-lettres-en-python/76202/7 "2018-03-22T18:53:06Z")

</div>

Bon enfin de compte durant la journée je suis parvenu à faire fonctionner ces foutu scripts 😃

Pour l’explication je devais en fait récupérer une valeur sous forme de flottant et pouvoir effectuer un calcul selon l’unité.

Je penser au départ séparer ma valeur et l’unité par un espace afin de le trier à l’aide d’un .split() mais il m’aie apparu plus simple de travailler avec deux string.

Donc finalement ça donne quelque chose comme ça :

```auto
def umem(data):
    pdata=data.split('/')[0].split()
    vdata=re.sub(r'[^\d\.]', '',pdata[3])
    udata=re.sub(r'[\d\.]', '',pdata[3])
    value = size_options[udata[0]](vdata)
    return value 

```

J’ai simplement fait un **import re**  
Ce qui me permet du coup de pouvoir en plus exporter dynamiquement l’unité directement sur la plateforme de monitoring afin de pouvoir gérer les changement d’unité à la volée directement depuis le serveur Zabbix.

J’en ai profité pour ajouter une recalcule et une remontée d’informations de la data In et Out de chaque container … la grande classe en bref.

Au cas où ce type de script fonctionne sur du python2.7, je verrai pour le migrer vers du python3 lorsque j’en aurai le courage, j’en profiterai pour porter tous le monitoring via agent en mode actif par la même occasion.

Un grand merci à vous deux 😉
