Próbuję utworzyć prosty skrypt, który wybierze określone kolumny z polecenia UNIX {X0}}. Mogę użyć awk, ale jak możemy to zrobić w Pythonie?

Tutaj jest df -h Wyjście:

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

Chcę coś takiego:

Kolumna 1:

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

Kolumna 2:

Size
28G
814M 
485M   
9
user1610085 19 sierpień 2012, 18:24

8 odpowiedzi

Najlepsza odpowiedź

Możesz użyć op.popen, aby uruchomić polecenie i pobrać jego wyjście, a następnie splitlines i {{split, aby podzielić linie i pola. Uruchom df -Ph, a nie df -h, więc linie nie są podzielone, jeśli Kolumna jest za długa.

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

Rezultatem jest lista linii. Aby wyodrębnić pierwszą kolumnę, możesz użyć [line[0] for line in df_output_lines] (Uwaga, że kolumny są ponumerowane od 0) i tak dalej. Możesz użyć df_output_lines[1:] zamiast df_output_lines, aby usunąć linię tytułu.

Jeśli masz już wyjście df -h zapisane gdzieś w pliku, musisz najpierw dołączyć do linii.

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

Zauważ, że zakłada, że ani nazwa systemu plików, ani punkt montowania zawierają białe znaki. Jeśli to zrobią (co jest możliwe z pewnymi konfiguracjami na niektórych wariantach UNIX), praktycznie niemożliwe jest przeanalizowanie wyjścia df, nawet df -P. Możesz użyć os.statvfs, aby uzyskać informacje na temat danego systemu plików (to jest python interfejs do C Funkcja że df połączenia wewnętrznie dla każdego systemu plików), ale jest Brak przenośnego sposobu wyliczenia systemów plików.

12
Gilles 'SO- stop being evil' 19 sierpień 2012, 15:06

Oto pełny przykład:

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]

Zakłada, że punkty montażu nie zawierają spacji.

Oto bardziej kompletny (i skomplikowane rozwiązanie), które nie ma numeru kolorów:

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]
2
Zaar Hai 19 sierpień 2012, 15:37

Nie odpowiedź na pytanie, ale starałem się rozwiązać problem. :)

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)
2
eminor 20 sierpień 2012, 03:41

Nie używając os.popen, ponieważ jest przestarzały (http://docs.PYTHON.org/library/os#os.popen).

Umieściłem wyjście DF -H w pliku: test.txt i czytaj z tego pliku. Ale możesz czytać także za pomocą subprocess. Wystarczy zakładając, że możesz przeczytać każdą linię wyjścia DF -H, pomoże Ci następujący kod: -

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

Każda kolumna wyświetli całą kolumnę jako liście. Możesz po prostu iterować nad nim. Jeśli potrzebujesz, mogę podać kod do czytania wyjścia z DF -H, dzięki czemu można usunąć zależność od test.txt, ale jeśli przejdziesz do dokumentacji podprocesowej, możesz znaleźć jak łatwo zrobić.

1
GodMan 19 sierpień 2012, 15:30

Miałem w sobie punkt do góry. To rzuciło większość przykładów. To pożycza dużo z @aHarhai 's Przykład, ale stawia wynik w 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)
1
Community 23 maj 2017, 12:09

Znalazłem to jako łatwy sposób na to ...

df -h |  awk '{print $1}'
1
user3868300user3868300 11 sierpień 2015, 12:33

To działa:

#!/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
0
dawg 19 sierpień 2012, 15:18

Jedną z rzeczy, które zauważyłem we wszystkich systemach, do których dostęp do: DF z drukowanami opcji -p w wyrównanych białych kolumnach. Oznacza to, że nagłówki są taką samą szerokość (wyściełaną białe znaki) jako reszta elementów. Budynek na Odpowiedź 7RMIM, wykorzystuje rozmiar nagłówka, aby zapewnić, że dostanie cały punkt montowania, nawet jeśli jest przestrzeń w nim.

Zostało to przetestowane na Ubuntu 14.04, 16.04 i FreeBSD 9.2.

Rozwiązałem te dwa różne sposoby, pierwsza jest bezpośrednią odpowiedzią na pytanie OP, dając 6 kolumn, z których każdy zaczyna się od nagłówka, a następnie ma każdy punkt montowania w kolejności poniżej:

import pprint
import subprocess
import re

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

# Get the entire output of df
dfdata = subprocess.getoutput("df " + DF_OPTIONS)

# Split it based on newlines
lines = dfdata.split("\n")

dfout = {}
headers = []

# Grab the headers, retain whitespace!
# df formats in such a way that each column header has trailing whitespace 
# so the header is equal to the maximum column width. We want to retain
# this for len()
headersplit = re.split(r'(\s+)', lines[0].replace("Mounted on","Mounted_on "))
headers = [i+j for i,j in zip(headersplit[0::2],headersplit[1::2])]

for hi,head in enumerate(headers):
  dfout[hi] = [head.strip()]

for line in lines[1:]:
  pos = 0
  dfstruct = {}
  for hi,head in enumerate(headers):
    # For the last item, grab the rest of the line
    if head == headers[-1]:
      item = line[pos:]
    else:
      # Get the current item
      item = line[pos:pos+len(head)]

    pos = pos + len(head)

    #Strip whitespace and add it to the list

    dfstruct[head.strip()] = item.strip()
    dfout[hi].append(item.strip())

pprint.pprint(dfout)

Drugi jest dla mnie bardziej przydatny, a rozwiązanie dlaczego natknęłam się na to pytanie w pierwszej kolejności. Dotyczy to informacji w tablicy dyktatów:

import pprint
import subprocess
import re

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

# Get the entire output of df
dfdata = subprocess.getoutput("df " + DF_OPTIONS)

# Split it based on newlines
lines = dfdata.split("\n")

dfout = []
headers = []

# Grab the headers, retain whitespace!
# df formats in such a way that each column header has trailing whitespace 
# so the header is equal to the maximum column width. We want to retain
# this for len()
headersplit = re.split(r'(\s+)', lines[0].replace("Mounted on","Mounted_on "))
headers = [i+j for i,j in zip(headersplit[0::2],headersplit[1::2])]

for line in lines[1:]:
  pos = 0
  dfstruct = {}
  for head in headers:
    # For the last item, grab the rest of the line
    if head == headers[-1]:
      item = line[pos:]
    else:
      # Get the current item
      item = line[pos:pos+len(head)]

    pos = pos + len(head)
    #Strip whitespace for our own structure
    dfstruct[head.strip()] = item.strip()

  dfout.append(dfstruct)

pprint.pprint(dfout)
0
Michael 10 październik 2018, 12:41