写在最前
说来也奇怪,人人都标榜圆满之后的不破不立,但为人初时想做一些规矩之外的事,却被说成是大逆不道。世人皆言,走过千山万水,再看山不是山,才能悟得非常道。你我都没有剧中所言传承之类的秘法,从一无所知修到一无所知,究竟是返璞归真,还是可怜的命运循环。所谓慈悲,都是执著。
当然,说回主题,Linux一众命令可以轻易实现的结果,为何还要做这些毫无意义的事。可能这就是我们这一代人的倔强,是不是苦果子,得自己尝过了才知道。口口声声以肉身证道,凡人哪有什么登天路,不过是拾级而上,守正扶弱而已。
目的
格式化行式命令输出1为字典类型。
代码
sshcmd.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from dataclasses import dataclass
@dataclass
class LineFeature:
keyword: str = None
prefix: str = None
suffix: str = None
@dataclass
class DelmtIndexType:
delimiter: str = None
index: int = None
@dataclass
class KeyValuePair:
feature: LineFeature = None
key: list[DelmtIndexType] = None
value: list[DelmtIndexType] = None
@dataclass
class LineCmd:
cmd: str = None
key_value_pairs: list[KeyValuePair] = None
delimiter: str = None
ikey: str = '0:1'
ivalue: str = '1:'
ssh.py
def formatline(self, linecmd: LineCmd = None):
cmd = linecmd.cmd
data = {}
exitcode, output = self.getstatusoutput(cmd)
if exitcode != 0:
return None
def fetch_value(l_info: list[DelmtIndexType] = None,
dataline: str = None) -> str:
for delimiter_index in l_info:
dlm = delimiter_index.delimiter
idx = delimiter_index.index
try:
dataline = dataline.split(dlm)[idx].strip()
except IndexError:
continue
return dataline
if linecmd.delimiter:
for ln in output.split('\n'):
ln = ln.strip()
ikey_from, ikey_to = linecmd.ikey.split(':')
ival_from, ival_to = linecmd.ivalue.split(':')
delimiter = linecmd.delimiter
try:
lst = [l.strip() for l in ln.split(delimiter)]
ikey_from = int(ikey_from)
ival_from = int(ival_from)
try:
ikey_to = int(ikey_to)
except ValueError:
ikey_to = None
try:
ival_to = int(ival_to)
except ValueError:
ival_to = None
key = f'{delimiter}'.join(lst[ikey_from:ikey_to])
value = f'{delimiter}'.join(lst[ival_from:ival_to])
data.update({key: value})
except IndexError:
continue
if not linecmd.key_value_pairs:
return data
for key_value in linecmd.key_value_pairs:
feature = key_value.feature
l_info_key = key_value.key
l_info_value = key_value.value
key_dataline = val_dataline = None
for ln in output.split('\n'):
ln = ln.strip()
pre = feature.prefix
key = feature.keyword
suf = feature.suffix
pre = pre if pre else ''
key = key if key else ''
suf = suf if suf else ''
if ln.startswith(pre) and ln.endswith(suf) and key in ln:
key_dataline = val_dataline = ln.strip()
key_dataline = fetch_value(l_info_key, key_dataline)
val_dataline = fetch_value(l_info_value, val_dataline)
data.update({key_dataline: val_dataline})
return data
测试验证
取命令lscpu
中:1. 以L1d
开头的键值; 2. 以BIOS开头包含关键字name的键值
定义LineCmd对象
方法1:
line_cmd = LineCmd(cmd='lscpu', key_value_pairs=[
KeyValuePair(feature=LineFeature(prefix='L1d'),
key=[DelmtIndexType(delimiter=':', index=0)],
value=[DelmtIndexType(':', index=1)]),
KeyValuePair(feature=LineFeature(prefix='BIOS', keyword='name'),
key=[DelmtIndexType(delimiter=':', index=0)],
value=[DelmtIndexType(':', 1), DelmtIndexType(' ', 2)])
])
方法2: 定义YAML文件
---
sshcmd:
- cmd: 'lscpu'
key_value_pairs:
- feature:
prefix: 'L1d'
key:
- delimiter: ':'
index: 0
value:
- delimiter: ':'
index: 1
- feature:
prefix: 'BIOS'
keyword: 'name'
key:
- delimiter: ':'
index: 0
value:
- delimiter: ':'
index: 1
- delimiter: ' '
index: 2
>>> from yaml import safe_load
>>>
>>> with open('../../devlist/examples/example.ssh.linux.yaml', 'r+') as f:
... line = safe_load(f)
...
>>> line
{'sshcmd': [{'cmd': 'lscpu', 'key_value_pairs': [{'feature': {'prefix': 'L1d'}, 'key': [{'delimiter': ':', 'index': 0}], 'value': [{'delimiter': ':', 'index': 1}]}, {'feature': {'prefix': 'BIOS', 'keyword': 'name'}, 'key': [{'delimiter': ':', 'index': 0}], 'value': [{'delimiter': ':', 'index': 1}, {'delimiter': ' ', 'index': 2}]}]}]}
>>>
结果验证:
$ python3 ssh.py
{'L1d cache': '64 KiB (2 instances)', 'BIOS Model name': 'i7-2640M'}
- 行式命令输出: 即命令输出内容单行格式为‘键+分隔符+值’的行,如'lscpu'输出某行为'Stepping: 2'。 ↩