Выбор определенных столбцов из вывода df-h в python

Я пытаюсь создать простой скрипт, который будет выбирать определенные столбцы из unix . Я могу использовать awk для этого, но как мы можем сделать это в python?

здесь df -h выход:

Filesystem                    Size  Used  Avail  Use%  Mounted on
/dev/mapper/vg_base-lv_root   28G   4.8G    22G   19%  /
tmpfs                        814M   176K   814M    1%  /dev/shm
/dev/sda1                    485M   120M   340M   27%  /boot

Я хочу что-то вроде:

колонка 1:

Filesystem
/dev/mapper/vg_base-lv_root           
tmpfs                 
/dev/sda1

колонка 2:

Size
28G
814M 
485M   

7 ответов


можно использовать op.popen чтобы запустить команду и получить ее вывод, затем splitlines и split для разделения строк и полей. Запустить df -Ph, а не df -h чтобы строки не разделялись, если столбец слишком длинный.

df_output_lines = [s.split() for s in os.popen("df -Ph").read().splitlines()]

результатом является список строк. Для извлечения первого столбца можно использовать [line[0] for line in df_output_lines] (обратите внимание, что столбцы нумеруются от 0) и так далее. Вы можете использовать df_output_lines[1:] вместо df_output_lines чтобы удалить строку заголовка.

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

fixed_df_output = re.sub('\n\s+', ' ', raw_df_output.read())
df_output_lines = [s.split() for s in fixed_df_output.splitlines()]

обратите внимание, что это предполагает, что ни имя файловой системы, ни точка монтирования не содержат пробелов. Если они это делают (что возможно с некоторыми настройками на некоторых вариантах unix), практически невозможно проанализировать вывод df, даже df -P. Вы можете использовать os.statvfs получить информацию в данной файловой системе (это интерфейс Python для функции C это df вызывает внутренне для каждой файловой системы), но нет переносимого способа перечисления файловых систем.


вот пример:

import subprocess
import re

p = subprocess.Popen("df -h", stdout=subprocess.PIPE, shell=True)
dfdata, _ = p.communicate()

dfdata = dfdata.replace("Mounted on", "Mounted_on")

columns = [list() for i in range(10)]
for line in dfdata.split("\n"):
    line = re.sub(" +", " ", line)
    for i,l in enumerate(line.split(" ")):
        columns[i].append(l)

print columns[0]

its предполагает, что точки монтирования не содержат пробелов.

вот более полное (и сложное решение), которое не содержит жесткого количества столбцов:

import subprocess
import re

def yield_lines(data):
    for line in data.split("\n"):
        yield line

def line_to_list(line):
    return re.sub(" +", " ", line).split()

p = subprocess.Popen("df -h", stdout=subprocess.PIPE, shell=True)
dfdata, _ = p.communicate()

dfdata = dfdata.replace("Mounted on", "Mounted_on")

lines = yield_lines(dfdata)

headers = line_to_list(lines.next())

columns = [list() for i in range(len(headers))]
for i,h in enumerate(headers):
    columns[i].append(h)

for line in lines:
    for i,l in enumerate(line_to_list(line)):
        columns[i].append(l)

print columns[0]

Не ответ на вопрос, но я пытался решить проблему. :)

from os import statvfs

with open("/proc/mounts", "r") as mounts:
    split_mounts = [s.split() for s in mounts.read().splitlines()]

    print "{0:24} {1:24} {2:16} {3:16} {4:15} {5:13}".format(
            "FS", "Mountpoint", "Blocks", "Blocks Free", "Size", "Free")
    for p in split_mounts:
        stat = statvfs(p[1])
        block_size = stat.f_bsize
        blocks_total = stat.f_blocks
        blocks_free = stat.f_bavail

        size_mb = float(blocks_total * block_size) / 1024 / 1024
        free_mb = float(blocks_free * block_size) / 1024 / 1024

        print "{0:24} {1:24} {2:16} {3:16} {4:10.2f}MiB {5:10.2f}MiB".format(
                p[0], p[1], blocks_total, blocks_free, size_mb, free_mb)

не используя ОС.popen как это устарело (http://docs.python.org/library/os#os.popen).

Я поместил вывод df-h в файл: test.txt и просто чтение из этого файла. Но вы также можете читать с помощью подпроцесса. Просто предполагая, что вы можете прочитать каждую строку вывода df-h, следующий код поможет: -

f = open('test.txt')

lines = (line.strip() for line in f.readlines())
f.close()    
splittedLines = (line.split() for line in lines)
listOfColumnData = zip(*splittedLines)
for eachColumn in listOfColumnData:
    print eachColumn

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


у меня была точка монтирования с пробелом в нем. Это отбросило большинство примеров. Это занимает много от @ZarrHai ' s пример но ставит результат в dict

#!/usr/bin/python
import subprocess
import re
from pprint import pprint

DF_OPTIONS = "-laTh" # remove h if you want bytes.

def yield_lines(data):
    for line in data.split("\n"):
        yield line

def line_to_list(line):
    pattern = re.compile(r"([\w\/\s\-\_]+)\s+(\w+)\s+([\d\.]+?[GKM]|\d+)"
                          "\s+([\d\.]+[GKM]|\d+)\s+([\d\.]+[GKM]|\d+)\s+"
                          "(\d+%)\s+(.*)")
    matches = pattern.search(line)
    if matches:
        return matches.groups()
    _line = re.sub(r" +", " ", line).split()
    return _line

p = subprocess.Popen(["df", DF_OPTIONS], stdout=subprocess.PIPE)
dfdata, _ = p.communicate()

dfdata = dfdata.replace("Mounted on", "Mounted_on")

lines = yield_lines(dfdata)

headers = line_to_list(lines.next())

columns = [list() for i in range(len(headers))]
for i,h in enumerate(headers):
    columns[i].append(h)

grouped = {}
for li, line in enumerate(lines):
    if not line:
        continue
    grouped[li] = {}
    for i,l in enumerate(line_to_list(line)):
        columns[i].append(l)
        key = headers[i].lower().replace("%","")
        grouped[li][key] = l.strip()

pprint(grouped)

это работает:

#!/usr/bin/python

import os, re

l=[]
p=os.popen('df -h')
for line in p.readlines():
    l.append(re.split(r'\s{2,}',line.strip()))


p.close()

for subl in l:
    print subl

Я нашел это простой способ сделать это...

df -h |  awk '{print }'