Linux

Formatting Linux Line-Style Command Output

A Note Before We Begin Strange as it is, everyone praises breaking through to a new round after completion, but when a person first wants to do something outsid

A Note Before We Begin

Strange as it is, everyone praises breaking through to a new round after completion, but when a person first wants to do something outside the rules, it's called outrageous. The world says: after traveling over mountains and rivers, you see the mountains are no longer mountains, only then can you grasp the extraordinary Way. You and I have no secret techniques passed down from the dramas — going from knowing nothing to knowing nothing, is it a return to the original state, or a pitiful cycle of fate? What is called compassion is but attachment.

Of course, back to the subject — what Linux commands can easily achieve, why bother with all this meaningless effort. Maybe this is the stubbornness of our generation: whether it's a bitter fruit, you have to taste it yourself to know. Always talking about proving the Way with your body, but what kind of mortal has a road to heaven? It's just climbing step by step, upholding the righteous and supporting the weak.

Purpose

Format the row-style command output 1 into a dictionary type.

Code

  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

Testing & Verification

Get from command lscpu: 1. the key-value starting with L1d; 2. the key-value starting with BIOS that contains the keyword "name"

Define LineCmd Object

Method 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)])
                   ])

Method 2: define a YAML file

---
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}]}]}]}
>>>

Result verification:

$ python3 ssh.py
{'L1d cache': '64 KiB (2 instances)', 'BIOS Model name': 'i7-2640M'}

  1. Line-format command output: refers to a line whose single-line output follows the 'key+separator+value' format, e.g. one line of lscpu output is 'Stepping: 2'.
N
norvyn

独立 iOS 开发者,写字的人。在一座有海的城市,慢慢地做一些小而确定的东西。An independent iOS developer and writer — slowly making small, certain things in a city by the sea.

评论Comments

加载中…Loading…

留下评论Leave a comment