2017-01-09 6 views
2

Я запускаю утилиту, которая анализирует вывод команды df. Я фиксирую вывод и отправляю его в свой парсер. Вот пример:Анализ вывода команды - 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 

Вот функция:

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 

Однако я получаю следующий результат:

['/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'] 

Выпуск map -host, как предполагается, один элемент (для столбца Filesystem). Я попытался применить регулярное выражение tokens = re.split(r'\s{2,}', line) но результат был еще не правильно:

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

Что бы правильный способ разобрать выход?

+0

Вам нужно использовать другой разделитель, возможно, как '\ t'? Даже многократные пробелы должны работать. – Nishant

+0

Каждый столбец имеет фиксированную ширину. Вы можете попробовать расщепление на основе этого –

+0

@Nishant: Разделение на '\ t':' ['/ dev/disk2 1996082176 430874728 1564695448 22% 2429300 4292537979 0% /'] ' – cybertextron

ответ

0

Поскольку FS, вероятно, имеет несколько пробелов и до тех пор, пока вы можете заранее определить, что вы можете разделить с помощью разных разделителей и в конечном итоге объединить их.

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

Но это не будет работать в fs отделяется пробелом, как большой.

Согласен с комментарием, что использование os.statvfs(path) - лучший инструмент для этого. df будет звонить subprocess.

1

Если это то поведение, которое вы хотите, самый простой способ, который я вижу, - присоединиться к первому элементу массива, пока вы не достигнете числового элемента.

Так что-то вроде этого:

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:] 

В качестве альтернативы вы можете попробовать @ предложение cricket_007 в:

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

Просто расщепляется на одном или нескольких пространств, с последующей цифрой или /

>>> 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'] 
>>> 
Смежные вопросы