2012-08-19 24 views
8

Tôi đang cố gắng tạo một tập lệnh đơn giản sẽ chọn các cột cụ thể từ lệnh unix df - h. Tôi có thể sử dụng awk để làm điều này nhưng làm thế nào chúng ta có thể làm điều này trong python?Chọn các cột cụ thể từ đầu ra df -h trong python

Đây là df -h đầu ra:

 
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 

Tôi muốn một cái gì đó như:

Cột 1:

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

Cột 2:

 
Size 
28G 
814M 
485M 

Trả lời

10

Bạn có thể sử dụng op.popen để chạy lệnh và truy xuất đầu ra của nó, sau đó splitlinessplit để chia các dòng và trường. Chạy df -Ph thay vì df -h để các dòng không bị phân tách nếu cột quá dài.

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

Kết quả là danh sách các dòng. Để trích xuất cột đầu tiên, bạn có thể sử dụng [line[0] for line in df_output_lines] (lưu ý rằng các cột được đánh số từ 0), v.v. Bạn có thể muốn sử dụng df_output_lines[1:] thay vì df_output_lines để tách dòng tiêu đề.

Nếu bạn đã có đầu ra của df -h được lưu trữ trong một tệp ở đâu đó, trước tiên bạn sẽ cần phải tham gia các dòng.

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

Lưu ý rằng điều này giả định rằng cả tên hệ thống tệp lẫn điểm gắn kết đều không chứa khoảng trắng. Nếu họ làm (có thể với một số thiết lập trên một số biến thể unix), nó thực tế không thể phân tích đầu ra của df, thậm chí df -P. Bạn có thể sử dụng os.statvfs để lấy thông tin về một hệ thống tệp nhất định (đây là giao diện Python cho C function rằng các cuộc gọi df nội bộ cho từng hệ thống tệp), nhưng không có cách nào để liệt kê các hệ thống tệp.

+0

Ngoài os.statvfs Python 3.3 sẽ thêm một hàm mới [shutil.disk_usage] (http://docs.python.org/dev/library/shutil.html#shutil.disk_usage) trả về một tuple có tên với tổng số thuộc tính, không gian được sử dụng và không gian trống. – miles82

+1

Ưu tiên quy trình con thay vì os.popen, vì os.popen không được chấp nhận (http://docs.python.org/library/os#os.popen). – GodMan

+0

Cảm ơn @Gilles. Tôi đã thử tùy chọn đầu tiên và nó đã hoạt động. Tôi đã phải làm như thế này cho mô-đun subprocess. ** df_output_lines = [s.split() cho s trong tiến trình con.Popen (["df", "-Ph"], stdout = subprocess.PIPE) .communicate() [0] .strip(). splitlines()] ** – user1610085

2

Dưới đây là ví dụ hoàn chỉnh:

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] 

nó giả định rằng điểm lắp không chứa khoảng trắng.

Đây là (giải pháp và phức tạp) hoàn chỉnh hơn mà không cứng lõi số cột:

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] 
+0

Không nên viết mã cứng các cột là 10. Nó nên được giữ năng động để đảm bảo rằng mã hoạt động trên các hương vị khác nhau của linux/unix – GodMan

+0

Bạn đúng tất nhiên. Tôi đã giả định rằng tác giả câu hỏi là một người mới bắt đầu Python và không muốn làm phức tạp câu trả lời không cần thiết. Tôi đã thêm mã thay thế mà không giả định số cột. –

1

Không sử dụng os.popen vì nó bị phản đối (http://docs.python.org /library/os#os.popen).

Tôi đã đặt đầu ra của df -h trong một tệp: test.txt và chỉ đọc từ tệp này. Tuy nhiên, bạn cũng có thể đọc bằng cách sử dụng tiến trình con. Chỉ cần giả định rằng bạn có thể đọc từng dòng đầu ra của df -h, mã sau đây sẽ giúp: -

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 sẽ hiển thị toàn bộ cột bạn muốn làm danh sách. Bạn chỉ có thể lặp lại nó. Nếu bạn cần, tôi có thể cung cấp cho mã để đọc đầu ra từ df -h để bạn có thể loại bỏ sự phụ thuộc vào test.txt, nhưng nếu bạn vào tài liệu quy trình con, bạn có thể tìm cách làm điều đó dễ dàng.

0

này hoạt động:

#!/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

Điều này không hoạt động khi chúng tôi nhận được kết quả sau: - [['Hệ thống tập tin', 'Kích thước', 'Sử dụng sử dụng được sử dụng% gắn trên'], ['/ dev/mapper/vg_base-lv_root', '28G' , '4.8G', '22G', '19%/'], [' tmpfs ',' 814M ',' 176K ',' 814M ',' 1%/dev/shm '], ['/dev /sda1 ',' 485M ',' 120M ',' 340M ', '27%/khởi động']] Có 2 vấn đề trong mã này: - 1. Các mục không được chia đúng theo yêu cầu, như hiển nhiên trong mục đầu tiên của danh sách l 2. Sau khi vấn đề 1 được giải quyết, yêu cầu của user1610085 là lấy dữ liệu ở định dạng được chuyển đổi. Đầu ra của bạn chỉ cho tất cả các dòng được chia tách, nhưng không được chuyển đổi – GodMan

+0

Tôi có thể giải quyết vấn đề 2 bằng 'cho tôi trong [dòng [0] cho dòng trong df_output_lines]: ... in i ' – user1610085

2

Không phải là câu trả lời cho câu hỏi, nhưng tôi đã cố gắng để giải quyết vấn đề. :)

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) 
1

Tôi có điểm gắn kết với khoảng trống trong đó. Điều này đã ném ra hầu hết các ví dụ. Đây vay mượn rất nhiều từ @ZarrHai 's example nhưng đặt kết quả trong một 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) 
+0

Bạn có thể muốn thêm thuộc tính liên kết đến những câu trả lời mà bạn đã vẽ từ đó. –

+0

@NathanTuggy Tôi thường không bình luận về những điều này. Bạn sẽ phân bổ như thế nào? Một liên kết đến ví dụ ban đầu? – the7erm

+0

Vâng, điều đó sẽ ổn thôi. –

0

tôi thấy cách này là dễ dàng để làm điều đó ...

df -h | awk '{print $1}' 
Các vấn đề liên quan