mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-06-19 00:17:51 +02:00
rewrite of lsblk parser to use a custom delimiter
This commit is contained in:
@ -4,7 +4,7 @@ jc changelog
|
|||||||
- Add -r and raw=True options. By default, jc will now convert numbers and boolean, if possible, and add other semantic information, while the raw output will keep all values as text and provide a more literal JSON output
|
- Add -r and raw=True options. By default, jc will now convert numbers and boolean, if possible, and add other semantic information, while the raw output will keep all values as text and provide a more literal JSON output
|
||||||
- Add -q and quiet=True options to suppress warnings to stderr
|
- Add -q and quiet=True options to suppress warnings to stderr
|
||||||
- Add compatibility warnings to stderr
|
- Add compatibility warnings to stderr
|
||||||
- Updated lsof parser to allow parsing of added columns
|
- Updated lsblk parser to allow parsing of added columns
|
||||||
- Updated mount parser: changed 'access' field name to 'options'
|
- Updated mount parser: changed 'access' field name to 'options'
|
||||||
- Updated netstat parser to allow parsing of unix sockets and raw network connections
|
- Updated netstat parser to allow parsing of unix sockets and raw network connections
|
||||||
- Updated w parser to fix unaligned data where blanks are possible
|
- Updated w parser to fix unaligned data where blanks are possible
|
||||||
|
@ -3,151 +3,12 @@
|
|||||||
Usage:
|
Usage:
|
||||||
specify --lsblk as the first argument if the piped input is coming from lsblk
|
specify --lsblk as the first argument if the piped input is coming from lsblk
|
||||||
|
|
||||||
Limitations:
|
|
||||||
the following columns can only be used as the last column:
|
|
||||||
HCTL
|
|
||||||
LABEL
|
|
||||||
MODEL
|
|
||||||
MOUNTPOINT
|
|
||||||
PARTLABEL
|
|
||||||
PARTUUID
|
|
||||||
PKNAME
|
|
||||||
REV
|
|
||||||
SERIAL
|
|
||||||
STATE
|
|
||||||
SCHED
|
|
||||||
TRAN
|
|
||||||
UUID
|
|
||||||
VENDOR
|
|
||||||
WWN
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
$ lsblk -o +STATE | jc --lsblk -p
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "sda",
|
|
||||||
"maj_min": "8:0",
|
|
||||||
"rm": false,
|
|
||||||
"size": "20G",
|
|
||||||
"ro": false,
|
|
||||||
"type": "disk",
|
|
||||||
"mountpoint": null,
|
|
||||||
"state": "running"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sda1",
|
|
||||||
"maj_min": "8:1",
|
|
||||||
"rm": false,
|
|
||||||
"size": "1G",
|
|
||||||
"ro": false,
|
|
||||||
"type": "part",
|
|
||||||
"mountpoint": "/boot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sda2",
|
|
||||||
"maj_min": "8:2",
|
|
||||||
"rm": false,
|
|
||||||
"size": "19G",
|
|
||||||
"ro": false,
|
|
||||||
"type": "part",
|
|
||||||
"mountpoint": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "centos-root",
|
|
||||||
"maj_min": "253:0",
|
|
||||||
"rm": false,
|
|
||||||
"size": "17G",
|
|
||||||
"ro": false,
|
|
||||||
"type": "lvm",
|
|
||||||
"mountpoint": "/",
|
|
||||||
"state": "running"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "centos-swap",
|
|
||||||
"maj_min": "253:1",
|
|
||||||
"rm": false,
|
|
||||||
"size": "2G",
|
|
||||||
"ro": false,
|
|
||||||
"type": "lvm",
|
|
||||||
"mountpoint": "[SWAP]",
|
|
||||||
"state": "running"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sr0",
|
|
||||||
"maj_min": "11:0",
|
|
||||||
"rm": true,
|
|
||||||
"size": "1024M",
|
|
||||||
"ro": false,
|
|
||||||
"type": "rom",
|
|
||||||
"mountpoint": null,
|
|
||||||
"state": "running"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
$ lsblk -o +STATE | jc --lsblk -p -r
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "sda",
|
|
||||||
"maj_min": "8:0",
|
|
||||||
"rm": "0",
|
|
||||||
"size": "20G",
|
|
||||||
"ro": "0",
|
|
||||||
"type": "disk",
|
|
||||||
"mountpoint": null,
|
|
||||||
"state": "running"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sda1",
|
|
||||||
"maj_min": "8:1",
|
|
||||||
"rm": "0",
|
|
||||||
"size": "1G",
|
|
||||||
"ro": "0",
|
|
||||||
"type": "part",
|
|
||||||
"mountpoint": "/boot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sda2",
|
|
||||||
"maj_min": "8:2",
|
|
||||||
"rm": "0",
|
|
||||||
"size": "19G",
|
|
||||||
"ro": "0",
|
|
||||||
"type": "part",
|
|
||||||
"mountpoint": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "centos-root",
|
|
||||||
"maj_min": "253:0",
|
|
||||||
"rm": "0",
|
|
||||||
"size": "17G",
|
|
||||||
"ro": "0",
|
|
||||||
"type": "lvm",
|
|
||||||
"mountpoint": "/",
|
|
||||||
"state": "running"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "centos-swap",
|
|
||||||
"maj_min": "253:1",
|
|
||||||
"rm": "0",
|
|
||||||
"size": "2G",
|
|
||||||
"ro": "0",
|
|
||||||
"type": "lvm",
|
|
||||||
"mountpoint": "[SWAP]",
|
|
||||||
"state": "running"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sr0",
|
|
||||||
"maj_min": "11:0",
|
|
||||||
"rm": "1",
|
|
||||||
"size": "1024M",
|
|
||||||
"ro": "0",
|
|
||||||
"type": "rom",
|
|
||||||
"mountpoint": null,
|
|
||||||
"state": "running"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
"""
|
"""
|
||||||
import string
|
|
||||||
import jc.utils
|
import jc.utils
|
||||||
|
|
||||||
|
|
||||||
@ -191,7 +52,10 @@ def process(proc_data):
|
|||||||
"wwn": string,
|
"wwn": string,
|
||||||
"rand": boolean,
|
"rand": boolean,
|
||||||
"pkname": string,
|
"pkname": string,
|
||||||
"hctl": string
|
"hctl": string,
|
||||||
|
"tran": string,
|
||||||
|
"rev": string,
|
||||||
|
"vendor": string
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
'''
|
'''
|
||||||
@ -219,6 +83,11 @@ def process(proc_data):
|
|||||||
return proc_data
|
return proc_data
|
||||||
|
|
||||||
|
|
||||||
|
def parse_pairs(p_data):
|
||||||
|
'''Used if -P option is detected'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def parse(data, raw=False, quiet=False):
|
def parse(data, raw=False, quiet=False):
|
||||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||||
compatible = ['linux']
|
compatible = ['linux']
|
||||||
@ -232,29 +101,55 @@ def parse(data, raw=False, quiet=False):
|
|||||||
cleandata = list(filter(None, linedata))
|
cleandata = list(filter(None, linedata))
|
||||||
cleandata = data.splitlines()
|
cleandata = data.splitlines()
|
||||||
|
|
||||||
fix_headers = cleandata.pop(0).lower()
|
header_text = cleandata.pop(0).lower()
|
||||||
fix_headers = fix_headers.replace('maj:min', 'maj_min')
|
header_text = header_text.replace(':', '_')
|
||||||
fix_headers = fix_headers.replace('-', '_')
|
header_text = header_text.replace('-', '_')
|
||||||
|
header_text = header_text + ' '
|
||||||
|
|
||||||
# find mountpoint starting column for fixup
|
header_list = header_text.split()
|
||||||
mpt_col = fix_headers.find('mountpoint')
|
|
||||||
|
|
||||||
headers = fix_headers.split()
|
# find each column index and end position
|
||||||
|
header_search = [header_list[0]]
|
||||||
|
for h in header_list[1:]:
|
||||||
|
header_search.append(' ' + h + ' ')
|
||||||
|
|
||||||
|
header_spec_list = []
|
||||||
|
for i, column in enumerate(header_list[0:len(header_list) - 1]):
|
||||||
|
header_spec = {
|
||||||
|
'name': column,
|
||||||
|
'end': header_text.find(header_search[i + 1]) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# fix weird 'rev' column
|
||||||
|
if header_search[i + 1] == ' rev ':
|
||||||
|
end_fix = header_spec['end'] - 1
|
||||||
|
header_spec['end'] = end_fix
|
||||||
|
|
||||||
|
header_spec_list.append(header_spec)
|
||||||
|
|
||||||
# parse lines
|
# parse lines
|
||||||
if cleandata:
|
if cleandata:
|
||||||
for entry in cleandata:
|
for entry in cleandata:
|
||||||
output_line = {}
|
output_line = {}
|
||||||
|
|
||||||
# normalize data by inserting Null for missing data
|
# insert new separator since data can contain spaces
|
||||||
temp_line = entry.split(maxsplit=len(headers) - 1)
|
for col in reversed(header_list):
|
||||||
|
# find the right header_spec
|
||||||
|
for h_spec in header_spec_list:
|
||||||
|
if h_spec['name'] == col:
|
||||||
|
h_end = h_spec['end']
|
||||||
|
# insert \u2026 delimiter
|
||||||
|
entry = entry[:h_end] + '~' + entry[h_end:]
|
||||||
|
|
||||||
# fix mountpoint column, always at column 6
|
# create the entry list from the new delimiter
|
||||||
if len(entry) > mpt_col:
|
entry_list = entry.split('~', maxsplit=len(header_list) - 1)
|
||||||
if entry[mpt_col] in string.whitespace:
|
|
||||||
temp_line.insert(6, None)
|
|
||||||
|
|
||||||
output_line = dict(zip(headers, temp_line))
|
# clean up leading and trailing spaces in entry
|
||||||
|
clean_entry_list = []
|
||||||
|
for col in entry_list:
|
||||||
|
clean_entry_list.append(col.strip().rstrip())
|
||||||
|
|
||||||
|
output_line = dict(zip(header_list, clean_entry_list))
|
||||||
raw_output.append(output_line)
|
raw_output.append(output_line)
|
||||||
|
|
||||||
for entry in raw_output:
|
for entry in raw_output:
|
||||||
|
Reference in New Issue
Block a user