Выбор определенных столбцов из вывода 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