2017-01-09 2 views
2

Ich führe ein Dienstprogramm aus, das die Ausgabe des Befehls df analysiert. Ich nehme die Ausgabe auf und sende sie an meinen Parser. Hier ist ein Beispiel:Analysieren einer Befehlsausgabe - Python

Filesystem    512-blocks  Used Available Capacity iused  ifree %iused Mounted on 
/dev/disk2    1996082176 430874208 1564695968 22% 2429281 4292537998 0% /
devfs       668  668   0 100% 1156   0 100% /dev 
map -hosts       0   0   0 100%  0   0 100% /net 
map auto_home      0   0   0 100%  0   0 100% /home 

Hier ist die Funktion:

def parse_df(self, content): 
    """Parse the `df` content output 

    :param content: The command content output 
    :return: (list) A list of objects of the type being parsed 
    """ 
    entries = [] 
    if not content: 
     return entries 
    # Split the content by line and check if we should ignore first line 
    for line in content.split("\n"): 
     if line.startswith("Filesystem"): 
      continue 
     tokens = line.split() 
     print tokens 

aber ich folgende Ausgabe bekommen:

['/dev/disk2', '1996082176', '430876480', '1564693696', '22%', '2429288', '4292537991', '0%', '/'] 
['devfs', '668', '668', '0', '100%', '1156', '0', '100%', '/dev'] 
['map', '-hosts', '0', '0', '0', '100%', '0', '0', '100%', '/net'] 
['map', 'auto_home', '0', '0', '0', '100%', '0', '0', '100%', '/home'] 

Das Problem wird map -host soll ein einzelnes Element sein (für die Filesystem Spalte). Ich habe versucht, richtig einen regulären Ausdruck tokens = re.split(r'\s{2,}', line) aber das Ergebnis war gelten immer noch nicht:

['/dev/disk2', '1996082176 430869352 1564700824', '22% 2429289 4292537990', '0%', '/'] 

Was ist der richtige Weg sein würde, um die Ausgabe zu analysieren?

+0

Sie müssen ein anderes Trennzeichen wie '\ t' verwenden? Auch mehrere Leerzeichen sollten funktionieren. – Nishant

+0

Jede Spalte hat eine feste Breite. Sie könnten versuchen, basierend auf diesem Split –

+0

@Nishant: Split von '\ t':' ['/ dev/disk2 1996082176 430874728 1564695448 22% 2429300 4292537979 0% /'] ' – cybertextron

Antwort

0

Da FS wird wahrscheinlich mehrere Leerzeichen haben und solange Sie vorab festlegen können, dass Sie mit verschiedenen Trennzeichen teilen und sie schließlich kombinieren können.

fs, rest = re.split(r'\s{2,}', line, 1) 
result = [fs] + rest.split() 

Aber das wird nicht funktionieren wird fs wird von einem einzigen Raum wie ein großes getrennt.

Stimmen Sie mit Kommentaren überein, dass die Verwendung von os.statvfs(path) ein besseres Werkzeug dafür ist. df wäre ein subprocess Anruf.

1

Wenn dies das gewünschte Verhalten ist, ist der einfachste Weg, den ich sehen kann, das erste Element des Arrays zu verbinden, bis Sie ein numerisches Element erreichen.

So etwas, wie:

tokens = line.split() 
n = 1 
while n < len(tokens) and not tokens[n].isdigit(): 
    n += 1 
tokens[0] = ' '.join(tokens[:n]) 
tokens = [ tokens[0] ] + tokens[n:] 

Alternativ können Sie @ cricket_007 Vorschlag versuchen:

first_token = line[:15].strip() 
tokens = [ first_token ] + [ x.strip() for x in line[15:].split() ] 
2

Nur aufgeteilt auf einen oder mehrere Räume, die durch eine Ziffer oder /

>>> import re 
>>> s = '''/dev/disk2    1996082176 430874208 1564695968 22% 2429281 4292537998 0% /
devfs       668  668   0 100% 1156   0 100% /dev 
map -hosts       0   0   0 100%  0   0 100% /net 
map auto_home      0   0   0 100%  0   0 100% /home'''.splitlines() 
>>> for line in s: 
    print re.split(r'\s+(?=[\d/])', line) 


['/dev/disk2', '1996082176', '430874208', '1564695968', '22%', '2429281', '4292537998', '0%', '/'] 
['devfs', '668', '668', '0', '100%', '1156', '0', '100%', '/dev'] 
['map -hosts', '0', '0', '0', '100%', '0', '0', '100%', '/net'] 
['map auto_home', '0', '0', '0', '100%', '0', '0', '100%', '/home'] 
>>> 
gefolgt wurde