Python 使用正则表达式输出的磁盘使用情况的输出

Python 使用正则表达式输出的磁盘使用情况的输出,python,regex,bash,shell,Python,Regex,Bash,Shell,下面的代码(p=)生成此输出 servername300 | SUCCESS | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/sda1 3.7T 1.3T 2.4T 16% /data/disk1 /dev/sdj1 3.7T 1.3T 2.4T 36% /data/disk10 /dev/sdk1 3.7T 1.3T 2.4T 36% /data/d

下面的代码(p=)生成此输出

servername300 | SUCCESS | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       3.7T  1.3T  2.4T  16% /data/disk1
/dev/sdj1       3.7T  1.3T  2.4T  36% /data/disk10
/dev/sdk1       3.7T  1.3T  2.4T  36% /data/disk11
servername290 | SUCCESS | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       3.7T  1.4T  2.4T  36% /data/disk1
/dev/sdj1       3.7T  1.4T  2.4T  37% /data/disk10
/dev/sdk1       3.7T  1.4T  2.4T  37% /data/disk11
此代码获取此输出并计算磁盘是否超过5%不平衡

import re
from subprocess import Popen, PIPE

p = subprocess.check_output(["ansible","dev-data","-m","shell","-a","df -h /data/disk*"], stdin=PIPE)

regex = re.compile(r'\d{1,2}%')

result = [int(a[:-1]) for a in regex.findall(p)]

print min (result)
print max (result)

if max(result) - min(result) > 5:
print("Imbalanced!")
else:
print("Balanced!")
这将给我输出

 """16 37 Imbalanced"""
我想在输出中包括服务器和磁盘,例如
servername300 16 disk 1,servername290 37 disk 10

这是我到目前为止试过的

regex1 = re.compile(r'^servername\d* | \d{1,2}% |disk\d*')

result = [a for a in regex.findall(p)]

我需要帮助在我的输出中包含str和int。谢谢你

我个人会将其解析为一个表,而不是执行复杂的正则表达式,但是如果你坚持的话,模式将是:

^(\S+).*?\n.*?\n(?:^.*?(\d+)%\s+(.*?)(?:\s|$))+
这将为每个服务器条目提供一个匹配项,并在以下组中进行匹配:
[“servername300”、“16”、“/data/disk1”、“36”、“/data/disk10”等]

然而,Python的正则表达式(以及大多数正则表达式引擎)覆盖重复的捕获组,只给您最后一次捕获,因此在示例数据上运行上述操作只会产生
[[“servername300”、“36”、“/data/disk11”]、[“servername290”、“37”、“/data/disk11”]
。当然,您可以构建该模式,以包括您可能期望的任意多个磁盘的可选捕获,或者使用重复组的范围属性,直到耗尽所有磁盘,但这将很快变得非常难看,因此

您可以拆分作业—一种模式用于隔离服务器条目,另一种模式用于提取磁盘使用情况数据,然后只需找到记录服务器和磁盘数据的最小值和最大值,如:

import re
import subprocess

p = subprocess.check_output(["ansible","dev-data","-m","shell","-a","df -h /data/disk*"],
                            stdin=subprocess.PIPE)

# our patterns, self explanatory
SERVER_MATCH = re.compile(r"(?!</)(\S+)(?:.*?\n){2}((?:^/.*(?:\n|$))+)", re.MULTILINE)
DISK_MATCH = re.compile(r"(\d+)%\s+(\S+)")

min_use = 100, None, None  # store for minimum usage entry
max_use = 0, None, None    # store for maximum usage entry
for server in SERVER_MATCH.findall(p):  # get all the servers + their disks
    for disk in DISK_MATCH.findall(server[1]):  # get each disk (usage + mount point)
        disk_usage = int(disk[0])  # convert the usage to integer
        if disk_usage < min_use[0]:  # if current disk's usage is smaller than min_usage
            min_use = (disk_usage, server[0], disk[1])  # replace entry
        if disk_usage > max_use[0]:  # if current disk's usage is smaller than max_usage
            max_use = (disk_usage, server[0], disk[1])  # replace entry

if max_use[0] - min_use[0] > 5:  # check min/max entries for larger discrepancy than 5...
    print("Imbalanced!")  # Imbalanced, print the info:
    print("\tMIN: {1} {0}% {2}".format(*min_use)) 
    print("\tMAX: {1} {0}% {2}".format(*max_use))
else:
    print("Balanced!")
您的示例数据的输出。这就足以找到不平衡的范围,但如果您想保留所有记录,以便进行比“最小/最大”更稳健的分析,可以使用:

servers = {}
for server in SERVER_MATCH.findall(data):
    servers[server[0]] = [(int(disk[0]), disk[1]) for disk in DISK_MATCH.findall(server[1])]

这将为您提供一个
dict
,其中包含密钥的服务器名称,以及每个磁盘的
(用法,磁盘名称)
对列表。

我认为您最好的方法可能是在远程主机上放置一个
balanced.sh
脚本并执行该脚本。让该脚本为自己的磁盘解析其输出。
servers = {}
for server in SERVER_MATCH.findall(data):
    servers[server[0]] = [(int(disk[0]), disk[1]) for disk in DISK_MATCH.findall(server[1])]