1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-19 00:17:51 +02:00

formatting

This commit is contained in:
Kelly Brazil
2022-01-19 17:29:22 -08:00
parent d4c34098fa
commit 3701b4198a
86 changed files with 710 additions and 606 deletions

View File

@ -236,8 +236,6 @@ class info():
description = '`acpi` command parser' description = '`acpi` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['acpi'] magic_commands = ['acpi']
@ -257,7 +255,8 @@ def _process(proc_data):
List of Dictionaries. Structured data to conform to the schema. List of Dictionaries. Structured data to conform to the schema.
""" """
int_list = ['id', 'charge_percent', 'design_capacity_mah', 'last_full_capacity', 'last_full_capacity_percent'] int_list = ['id', 'charge_percent', 'design_capacity_mah', 'last_full_capacity',
'last_full_capacity_percent']
float_list = ['temperature'] float_list = ['temperature']
for entry in proc_data: for entry in proc_data:

View File

@ -89,9 +89,6 @@ class info():
description = '`airport -I` command parser' description = '`airport -I` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['darwin'] compatible = ['darwin']
magic_commands = ['airport -I'] magic_commands = ['airport -I']
@ -144,7 +141,9 @@ def parse(data, raw=False, quiet=False):
for line in filter(None, data.splitlines()): for line in filter(None, data.splitlines()):
linedata = line.split(':', maxsplit=1) linedata = line.split(':', maxsplit=1)
raw_output[linedata[0].strip().lower().replace(' ', '_').replace('.', '_')] = linedata[1].strip() key = linedata[0].strip().lower().replace(' ', '_').replace('.', '_')
value = linedata[1].strip()
raw_output[key] = value
if raw: if raw:
return raw_output return raw_output

View File

@ -118,9 +118,6 @@ class info():
description = '`airport -s` command parser' description = '`airport -s` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['darwin'] compatible = ['darwin']
magic_commands = ['airport -s'] magic_commands = ['airport -s']

View File

@ -127,8 +127,6 @@ class info():
description = '`arp` command parser' description = '`arp` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin'] compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['arp'] magic_commands = ['arp']

View File

@ -130,9 +130,6 @@ class info():
description = '`blkid` command parser' description = '`blkid` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['blkid'] magic_commands = ['blkid']
@ -156,9 +153,10 @@ def _process(proc_data):
if 'devname' in entry: if 'devname' in entry:
entry['device'] = entry.pop('devname') entry['device'] = entry.pop('devname')
int_list = ['part_entry_number', 'part_entry_offset', 'part_entry_size', 'id_part_entry_number', int_list = ['part_entry_number', 'part_entry_offset', 'part_entry_size',
'id_part_entry_offset', 'id_part_entry_size', 'minimum_io_size', 'physical_sector_size', 'id_part_entry_number', 'id_part_entry_offset', 'id_part_entry_size',
'logical_sector_size', 'id_iolimit_minimum_io_size', 'id_iolimit_physical_sector_size', 'minimum_io_size', 'physical_sector_size', 'logical_sector_size',
'id_iolimit_minimum_io_size', 'id_iolimit_physical_sector_size',
'id_iolimit_logical_sector_size'] 'id_iolimit_logical_sector_size']
for key in entry: for key in entry:
if key in int_list: if key in int_list:

View File

@ -63,8 +63,6 @@ class info():
description = '`cksum` and `sum` command parser' description = '`cksum` and `sum` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['cksum', 'sum'] magic_commands = ['cksum', 'sum']

View File

@ -1,4 +1,5 @@
"""jc - JSON CLI output utility `crontab -l` command output and crontab file parser """jc - JSON CLI output utility `crontab -l` command output and crontab
file parser
Supports `crontab -l` command output and crontab files. Supports `crontab -l` command output and crontab files.
@ -182,9 +183,6 @@ class info():
description = '`crontab` command and file parser' description = '`crontab` command and file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['crontab'] magic_commands = ['crontab']

View File

@ -1,6 +1,8 @@
"""jc - JSON CLI output utility `crontab -l` command output and crontab file parser """jc - JSON CLI output utility `crontab -l` command output and crontab
file parser
This version of the `crontab -l` parser supports output that contains user information for processes. This version of the `crontab -l` parser supports output that contains user
information for processes.
Usage (cli): Usage (cli):
@ -57,7 +59,7 @@ Examples:
"variables": [ "variables": [
{ {
"name": "PATH", "name": "PATH",
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" "value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sb..."
}, },
{ {
"name": "SHELL", "name": "SHELL",
@ -82,7 +84,7 @@ Examples:
"*" "*"
], ],
"user": "root", "user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )" "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..."
}, },
{ {
"minute": [ "minute": [
@ -101,7 +103,7 @@ Examples:
"7" "7"
], ],
"user": "root", "user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )" "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..."
}, },
{ {
"minute": [ "minute": [
@ -120,7 +122,7 @@ Examples:
"*" "*"
], ],
"user": "root", "user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )" "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..."
} }
] ]
} }
@ -130,7 +132,7 @@ Examples:
"variables": [ "variables": [
{ {
"name": "PATH", "name": "PATH",
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" "value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/..."
}, },
{ {
"name": "SHELL", "name": "SHELL",
@ -145,7 +147,7 @@ Examples:
"month": "*", "month": "*",
"day_of_week": "*", "day_of_week": "*",
"user": "root", "user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )" "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..."
}, },
{ {
"minute": "47", "minute": "47",
@ -154,7 +156,7 @@ Examples:
"month": "*", "month": "*",
"day_of_week": "7", "day_of_week": "7",
"user": "root", "user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )" "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..."
}, },
{ {
"minute": "52", "minute": "52",
@ -163,7 +165,7 @@ Examples:
"month": "*", "month": "*",
"day_of_week": "*", "day_of_week": "*",
"user": "root", "user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )" "command": "test -x /usr/sbin/anacron || ( cd / && run-parts ..."
} }
] ]
} }
@ -178,9 +180,6 @@ class info():
description = '`crontab` file parser with user support' description = '`crontab` file parser with user support'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']

View File

@ -1,6 +1,8 @@
"""jc - JSON CLI output utility `csv` file parser """jc - JSON CLI output utility `csv` file parser
The `csv` parser will attempt to automatically detect the delimiter character. If the delimiter cannot be detected it will default to comma. The first row of the file must be a header row. The `csv` parser will attempt to automatically detect the delimiter
character. If the delimiter cannot be detected it will default to comma. The
first row of the file must be a header row.
Usage (cli): Usage (cli):
@ -18,7 +20,8 @@ Usage (module):
Schema: Schema:
csv file converted to a Dictionary: https://docs.python.org/3/library/csv.html csv file converted to a Dictionary:
https://docs.python.org/3/library/csv.html
[ [
{ {
@ -30,7 +33,7 @@ Schema:
Examples: Examples:
$ cat homes.csv $ cat homes.csv
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes" "Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres"...
142, 160, 28, 10, 5, 3, 60, 0.28, 3167 142, 160, 28, 10, 5, 3, 60, 0.28, 3167
175, 180, 18, 8, 4, 1, 12, 0.43, 4033 175, 180, 18, 8, 4, 1, 12, 0.43, 4033
129, 132, 13, 6, 3, 1, 41, 0.33, 1471 129, 132, 13, 6, 3, 1, 41, 0.33, 1471
@ -85,8 +88,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the python standard csv library' details = 'Using the python standard csv library'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
@ -103,7 +104,8 @@ def _process(proc_data):
Returns: Returns:
List of Dictionaries. Each Dictionary represents a row in the csv file. List of Dictionaries. Each Dictionary represents a row in the csv
file.
""" """
# No further processing # No further processing

View File

@ -2,9 +2,12 @@
> This streaming parser outputs JSON Lines > This streaming parser outputs JSON Lines
The `csv` streaming parser will attempt to automatically detect the delimiter character. If the delimiter cannot be detected it will default to comma. The first row of the file must be a header row. The `csv` streaming parser will attempt to automatically detect the
delimiter character. If the delimiter cannot be detected it will default
to comma. The first row of the file must be a header row.
Note: The first 100 rows are read into memory to enable delimiter detection, then the rest of the rows are loaded lazily. Note: The first 100 rows are read into memory to enable delimiter detection,
then the rest of the rows are loaded lazily.
Usage (cli): Usage (cli):
@ -13,27 +16,33 @@ Usage (cli):
Usage (module): Usage (module):
import jc import jc
result = jc.parse('csv_s', csv_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parse('csv_s', csv_output.splitlines())
for item in result: for item in result:
# do something # do something
or or
import jc.parsers.csv_s import jc.parsers.csv_s
result = jc.parsers.csv_s.parse(csv_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parsers.csv_s.parse(csv_output.splitlines())
for item in result: for item in result:
# do something # do something
Schema: Schema:
csv file converted to a Dictionary: https://docs.python.org/3/library/csv.html csv file converted to a Dictionary:
https://docs.python.org/3/library/csv.html
{ {
"column_name1": string, "column_name1": string,
"column_name2": string, "column_name2": string,
"_jc_meta": # This object only exists if using -qq or ignore_exceptions=True
# below object only exists if using -qq or ignore_exceptions=True
"_jc_meta":
{ {
"success": boolean, # true if successfully parsed, false if error "success": boolean, # false if error parsing
"error": string, # exists if "success" is false "error": string, # exists if "success" is false
"line": string # exists if "success" is false "line": string # exists if "success" is false
} }
@ -42,16 +51,16 @@ Schema:
Examples: Examples:
$ cat homes.csv $ cat homes.csv
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes" "Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres"...
142, 160, 28, 10, 5, 3, 60, 0.28, 3167 142, 160, 28, 10, 5, 3, 60, 0.28, 3167
175, 180, 18, 8, 4, 1, 12, 0.43, 4033 175, 180, 18, 8, 4, 1, 12, 0.43, 4033
129, 132, 13, 6, 3, 1, 41, 0.33, 1471 129, 132, 13, 6, 3, 1, 41, 0.33, 1471
... ...
$ cat homes.csv | jc --csv-s $ cat homes.csv | jc --csv-s
{"Sell":"142","List":"160","Living":"28","Rooms":"10","Beds":"5","Baths":"3","Age":"60","Acres":"0.28","Taxes":"3167"} {"Sell":"142","List":"160","Living":"28","Rooms":"10","Beds":"5"...}
{"Sell":"175","List":"180","Living":"18","Rooms":"8","Beds":"4","Baths":"1","Age":"12","Acres":"0.43","Taxes":"4033"} {"Sell":"175","List":"180","Living":"18","Rooms":"8","Beds":"4"...}
{"Sell":"129","List":"132","Living":"13","Rooms":"6","Beds":"3","Baths":"1","Age":"41","Acres":"0.33","Taxes":"1471"} {"Sell":"129","List":"132","Living":"13","Rooms":"6","Beds":"3"...}
... ...
""" """
import itertools import itertools
@ -85,7 +94,8 @@ def _process(proc_data):
Returns: Returns:
List of Dictionaries. Each Dictionary represents a row in the csv file. List of Dictionaries. Each Dictionary represents a row in the csv
file.
""" """
# No further processing # No further processing
return proc_data return proc_data
@ -97,7 +107,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
Parameters: Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True ignore_exceptions: (boolean) ignore parsing exceptions if True

View File

@ -1,8 +1,10 @@
"""jc - JSON CLI output utility `date` command output parser """jc - JSON CLI output utility `date` command output parser
The `epoch` calculated timestamp field is naive. (i.e. based on the local time of the system the parser is run on) The `epoch` calculated timestamp field is naive. (i.e. based on the local
time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. The `epoch_utc` calculated timestamp field is timezone-aware and is only
available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -37,15 +39,19 @@ Schema:
"second": integer, "second": integer,
"period": string, "period": string,
"timezone": string, "timezone": string,
"utc_offset": string, # null if timezone field is not UTC "utc_offset": string, # null if timezone field is not UTC
"day_of_year": integer, "day_of_year": integer,
"week_of_year": integer, "week_of_year": integer,
"iso": string, "iso": string,
"epoch": integer, # naive timestamp "epoch": integer, # [0]
"epoch_utc": integer, # timezone-aware timestamp. Only available if timezone field is UTC "epoch_utc": integer, # [1]
"timezone_aware": boolean # if true, all fields are correctly based on UTC "timezone_aware": boolean # [2]
} }
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] if true, all fields are correctly based on UTC
Examples: Examples:
$ date | jc --date -p $ date | jc --date -p
@ -81,8 +87,6 @@ class info():
description = '`date` command parser' description = '`date` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['date'] magic_commands = ['date']
@ -129,28 +133,33 @@ def parse(data, raw=False, quiet=False):
# find the timezone no matter where it is in the string # find the timezone no matter where it is in the string
# from https://www.timeanddate.com/time/zones/ # from https://www.timeanddate.com/time/zones/
tz_abbr = ['A', 'ACDT', 'ACST', 'ACT', 'ACWST', 'ADT', 'AEDT', 'AEST', 'AET', 'AFT', 'AKDT', 'AKST', 'ALMT', tz_abbr = [
'AMST', 'AMT', 'ANAST', 'ANAT', 'AQTT', 'ART', 'AST', 'AT', 'AWDT', 'AWST', 'AZOST', 'AZOT', 'A', 'ACDT', 'ACST', 'ACT', 'ACWST', 'ADT', 'AEDT', 'AEST', 'AET', 'AFT', 'AKDT',
'AZST', 'AZT', 'AoE', 'B', 'BNT', 'BOT', 'BRST', 'BRT', 'BST', 'BTT', 'C', 'CAST', 'CAT', 'CCT', 'AKST', 'ALMT', 'AMST', 'AMT', 'ANAST', 'ANAT', 'AQTT', 'ART', 'AST', 'AT', 'AWDT',
'CDT', 'CEST', 'CET', 'CHADT', 'CHAST', 'CHOST', 'CHOT', 'CHUT', 'CIDST', 'CIST', 'CKT', 'CLST', 'AWST', 'AZOST', 'AZOT', 'AZST', 'AZT', 'AoE', 'B', 'BNT', 'BOT', 'BRST', 'BRT', 'BST',
'CLT', 'COT', 'CST', 'CT', 'CVT', 'CXT', 'ChST', 'D', 'DAVT', 'DDUT', 'E', 'EASST', 'EAST', 'BTT', 'C', 'CAST', 'CAT', 'CCT', 'CDT', 'CEST', 'CET', 'CHADT', 'CHAST', 'CHOST',
'EAT', 'ECT', 'EDT', 'EEST', 'EET', 'EGST', 'EGT', 'EST', 'ET', 'F', 'FET', 'FJST', 'FJT', 'FKST', 'CHOT', 'CHUT', 'CIDST', 'CIST', 'CKT', 'CLST', 'CLT', 'COT', 'CST', 'CT', 'CVT', 'CXT',
'FKT', 'FNT', 'G', 'GALT', 'GAMT', 'GET', 'GFT', 'GILT', 'GMT', 'GST', 'GYT', 'H', 'HDT', 'HKT', 'ChST', 'D', 'DAVT', 'DDUT', 'E', 'EASST', 'EAST', 'EAT', 'ECT', 'EDT', 'EEST', 'EET',
'HOVST', 'HOVT', 'HST', 'I', 'ICT', 'IDT', 'IOT', 'IRDT', 'IRKST', 'IRKT', 'IRST', 'IST', 'JST', 'EGST', 'EGT', 'EST', 'ET', 'F', 'FET', 'FJST', 'FJT', 'FKST', 'FKT', 'FNT', 'G',
'K', 'KGT', 'KOST', 'KRAST', 'KRAT', 'KST', 'KUYT', 'L', 'LHDT', 'LHST', 'LINT', 'M', 'MAGST', 'GALT', 'GAMT', 'GET', 'GFT', 'GILT', 'GMT', 'GST', 'GYT', 'H', 'HDT', 'HKT', 'HOVST',
'MAGT', 'MART', 'MAWT', 'MDT', 'MHT', 'MMT', 'MSD', 'MSK', 'MST', 'MT', 'MUT', 'MVT', 'MYT', 'N', 'HOVT', 'HST', 'I', 'ICT', 'IDT', 'IOT', 'IRDT', 'IRKST', 'IRKT', 'IRST', 'IST', 'JST',
'NCT', 'NDT', 'NFDT', 'NFT', 'NOVST', 'NOVT', 'NPT', 'NRT', 'NST', 'NUT', 'NZDT', 'NZST', 'O', 'K', 'KGT', 'KOST', 'KRAST', 'KRAT', 'KST', 'KUYT', 'L', 'LHDT', 'LHST', 'LINT', 'M',
'OMSST', 'OMST', 'ORAT', 'P', 'PDT', 'PET', 'PETST', 'PETT', 'PGT', 'PHOT', 'PHT', 'PKT', 'PMDT', 'MAGST', 'MAGT', 'MART', 'MAWT', 'MDT', 'MHT', 'MMT', 'MSD', 'MSK', 'MST', 'MT', 'MUT',
'PMST', 'PONT', 'PST', 'PT', 'PWT', 'PYST', 'PYT', 'Q', 'QYZT', 'R', 'RET', 'ROTT', 'S', 'SAKT', 'MVT', 'MYT', 'N', 'NCT', 'NDT', 'NFDT', 'NFT', 'NOVST', 'NOVT', 'NPT', 'NRT', 'NST',
'SAMT', 'SAST', 'SBT', 'SCT', 'SGT', 'SRET', 'SRT', 'SST', 'SYOT', 'T', 'TAHT', 'TFT', 'TJT', 'TKT', 'NUT', 'NZDT', 'NZST', 'O', 'OMSST', 'OMST', 'ORAT', 'P', 'PDT', 'PET', 'PETST', 'PETT',
'TLT', 'TMT', 'TOST', 'TOT', 'TRT', 'TVT', 'U', 'ULAST', 'ULAT', 'UYST', 'UYT', 'UZT', 'V', 'VET', 'PGT', 'PHOT', 'PHT', 'PKT', 'PMDT', 'PMST', 'PONT', 'PST', 'PT', 'PWT', 'PYST', 'PYT',
'VLAST', 'VLAT', 'VOST', 'VUT', 'W', 'WAKT', 'WARST', 'WAST', 'WAT', 'WEST', 'WET', 'WFT', 'WGST', 'Q', 'QYZT', 'R', 'RET', 'ROTT', 'S', 'SAKT', 'SAMT', 'SAST', 'SBT', 'SCT', 'SGT',
'WGT', 'WIB', 'WIT', 'WITA', 'WST', 'WT', 'X', 'Y', 'YAKST', 'YAKT', 'YAPT', 'YEKST', 'YEKT', 'Z', 'SRET', 'SRT', 'SST', 'SYOT', 'T', 'TAHT', 'TFT', 'TJT', 'TKT', 'TLT', 'TMT', 'TOST',
'UTC', 'UTC-1200', 'UTC-1100', 'UTC-1000', 'UTC-0930', 'UTC-0900', 'UTC-0800', 'UTC-0700', 'UTC-0600', 'TOT', 'TRT', 'TVT', 'U', 'ULAST', 'ULAT', 'UYST', 'UYT', 'UZT', 'V', 'VET', 'VLAST',
'UTC-0500', 'UTC-0400', 'UTC-0300', 'UTC-0230', 'UTC-0200', 'UTC-0100', 'UTC+0000', 'UTC-0000', 'VLAT', 'VOST', 'VUT', 'W', 'WAKT', 'WARST', 'WAST', 'WAT', 'WEST', 'WET', 'WFT',
'UTC+0100', 'UTC+0200', 'UTC+0300', 'UTC+0400', 'UTC+0430', 'UTC+0500', 'UTC+0530', 'UTC+0545', 'WGST', 'WGT', 'WIB', 'WIT', 'WITA', 'WST', 'WT', 'X', 'Y', 'YAKST', 'YAKT', 'YAPT',
'UTC+0600', 'UTC+0630', 'UTC+0700', 'UTC+0800', 'UTC+0845', 'UTC+0900', 'UTC+1000', 'UTC+1030', 'YEKST', 'YEKT', 'Z', 'UTC', 'UTC-1200', 'UTC-1100', 'UTC-1000', 'UTC-0930', 'UTC-0900',
'UTC+1100', 'UTC+1200', 'UTC+1300', 'UTC+1345', 'UTC+1400'] 'UTC-0800', 'UTC-0700', 'UTC-0600', 'UTC-0500', 'UTC-0400', 'UTC-0300', 'UTC-0230',
'UTC-0200', 'UTC-0100', 'UTC+0000', 'UTC-0000', 'UTC+0100', 'UTC+0200', 'UTC+0300',
'UTC+0400', 'UTC+0430', 'UTC+0500', 'UTC+0530', 'UTC+0545', 'UTC+0600', 'UTC+0630',
'UTC+0700', 'UTC+0800', 'UTC+0845', 'UTC+0900', 'UTC+1000', 'UTC+1030', 'UTC+1100',
'UTC+1200', 'UTC+1300', 'UTC+1345', 'UTC+1400'
]
tz = None tz = None
for term in data.replace('(', '').replace(')', '').split(): for term in data.replace('(', '').replace(')', '').split():
if term in tz_abbr: if term in tz_abbr:

View File

@ -108,8 +108,6 @@ class info():
description = '`df` command parser' description = '`df` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['df'] magic_commands = ['df']
@ -163,7 +161,8 @@ def _process(proc_data):
entry['iused_percent'] = entry['iused_percent'].rstrip('%') entry['iused_percent'] = entry['iused_percent'].rstrip('%')
# change used, available, use_percent, capacity_percent, ifree, iused, iused_percent to int # change used, available, use_percent, capacity_percent, ifree, iused, iused_percent to int
int_list = ['used', 'available', 'use_percent', 'capacity_percent', 'ifree', 'iused', 'iused_percent'] int_list = ['used', 'available', 'use_percent', 'capacity_percent', 'ifree',
'iused', 'iused_percent']
for key in entry: for key in entry:
if key in int_list: if key in int_list:
entry[key] = jc.utils.convert_to_int(entry[key]) entry[key] = jc.utils.convert_to_int(entry[key])
@ -172,7 +171,10 @@ def _process(proc_data):
def _long_filesystem_hash(header, line): def _long_filesystem_hash(header, line):
"""Returns truncated hash and value of the filesystem field if it is too long for the column""" """
Returns truncated hash and value of the filesystem field if it is too
long for the column.
"""
filesystem_field = line.split()[0] filesystem_field = line.split()[0]
# get length of filesystem column # get length of filesystem column
@ -238,7 +240,8 @@ def parse(data, raw=False, quiet=False):
# parse the data # parse the data
raw_output = jc.parsers.universal.sparse_table_parse(fix_data) raw_output = jc.parsers.universal.sparse_table_parse(fix_data)
# replace hash values with real values to fix long filesystem data in some older versions of df # replace hash values with real values to fix long filesystem data
# in some older versions of df
for item in raw_output: for item in raw_output:
if 'filesystem' in item: if 'filesystem' in item:
if item['filesystem'] in filesystem_map: if item['filesystem'] in filesystem_map:

View File

@ -1,12 +1,15 @@
"""jc - JSON CLI output utility `dig` command output parser """jc - JSON CLI output utility `dig` command output parser
Options supported: Options supported:
- `+noall +answer` options are supported in cases where only the answer information is desired. - `+noall +answer` options are supported in cases where only the answer
information is desired.
- `+axfr` option is supported on its own - `+axfr` option is supported on its own
The `when_epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `when_epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `when_epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. The `when_epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -95,13 +98,16 @@ Schema:
"query_time": integer, # in msec "query_time": integer, # in msec
"server": string, "server": string,
"when": string, "when": string,
"when_epoch": integer, # naive timestamp if when field is parsable, else null "when_epoch": integer, # [0]
"when_epoch_utc": integer, # timezone aware timestamp availabe for UTC, else null "when_epoch_utc": integer, # [1]
"rcvd": integer "rcvd": integer
"size": string "size": string
} }
] ]
[0] naive timestamp if when field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
Examples: Examples:
$ dig example.com | jc --dig -p $ dig example.com | jc --dig -p
@ -325,8 +331,6 @@ class info():
description = '`dig` command parser' description = '`dig` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin', 'win32', 'cygwin'] compatible = ['linux', 'aix', 'freebsd', 'darwin', 'win32', 'cygwin']
magic_commands = ['dig'] magic_commands = ['dig']
@ -347,8 +351,8 @@ def _process(proc_data):
List of Dictionaries. Structured data to conform to the schema. List of Dictionaries. Structured data to conform to the schema.
""" """
for entry in proc_data: for entry in proc_data:
int_list = ['id', 'query_num', 'answer_num', 'authority_num', 'additional_num', 'rcvd', int_list = ['id', 'query_num', 'answer_num', 'authority_num', 'additional_num',
'query_size', 'query_time'] 'rcvd', 'query_size', 'query_time']
for key in entry: for key in entry:
if key in int_list: if key in int_list:
entry[key] = jc.utils.convert_to_int(entry[key]) entry[key] = jc.utils.convert_to_int(entry[key])
@ -360,10 +364,12 @@ def _process(proc_data):
if 'opt_pseudosection' in entry: if 'opt_pseudosection' in entry:
if 'edns' in entry['opt_pseudosection']: if 'edns' in entry['opt_pseudosection']:
if 'version' in entry['opt_pseudosection']['edns']: if 'version' in entry['opt_pseudosection']['edns']:
entry['opt_pseudosection']['edns']['version'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['version']) val = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['version'])
entry['opt_pseudosection']['edns']['version'] = val
if 'udp' in entry['opt_pseudosection']['edns']: if 'udp' in entry['opt_pseudosection']['edns']:
entry['opt_pseudosection']['edns']['udp'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['udp']) val = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['udp'])
entry['opt_pseudosection']['edns']['udp'] = val
if 'answer' in entry: if 'answer' in entry:
for ans in entry['answer']: for ans in entry['answer']:

View File

@ -6,9 +6,11 @@ Options supported:
- `/C, /-C` - `/C, /-C`
- `/S` - `/S`
The "Magic" syntax is not supported since the `dir` command is a shell builtin. The "Magic" syntax is not supported since the `dir` command is a shell
builtin.
The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `epoch` calculated timestamp field is naive. (i.e. based on the local
time of the system the parser is run on)
Usage (cli): Usage (cli):
@ -128,8 +130,6 @@ class info():
description = '`dir` command parser' description = '`dir` command parser'
author = 'Rasheed Elsaleh' author = 'Rasheed Elsaleh'
author_email = 'rasheed@rebelliondefense.com' author_email = 'rasheed@rebelliondefense.com'
# compatible options: win32
compatible = ['win32'] compatible = ['win32']

View File

@ -134,9 +134,6 @@ class info():
description = '`dmidecode` command parser' description = '`dmidecode` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['dmidecode'] magic_commands = ['dmidecode']

View File

@ -1,6 +1,7 @@
"""jc - JSON CLI output utility `dpkg -l` command output parser """jc - JSON CLI output utility `dpkg -l` command output parser
Set the `COLUMNS` environment variable to a large value to avoid field truncation. For example: Set the `COLUMNS` environment variable to a large value to avoid field
truncation. For example:
$ COLUMNS=500 dpkg -l | jc --dpkg-l $ COLUMNS=500 dpkg -l | jc --dpkg-l
@ -74,7 +75,7 @@ Examples:
"name": "acpid", "name": "acpid",
"version": "1:2.0.28-1ubuntu1", "version": "1:2.0.28-1ubuntu1",
"architecture": "amd64", "architecture": "amd64",
"description": "Advanced Configuration and Power Interface event daemon", "description": "Advanced Configuration and Power Interface...",
"desired": "remove", "desired": "remove",
"status": "half installed" "status": "half installed"
}, },
@ -118,7 +119,7 @@ Examples:
"name": "acpid", "name": "acpid",
"version": "1:2.0.28-1ubuntu1", "version": "1:2.0.28-1ubuntu1",
"architecture": "amd64", "architecture": "amd64",
"description": "Advanced Configuration and Power Interface event daemon" "description": "Advanced Configuration and Power Interface..."
}, },
{ {
"codes": "pn", "codes": "pn",
@ -140,9 +141,6 @@ class info():
description = '`dpkg -l` command parser' description = '`dpkg -l` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['dpkg -l'] magic_commands = ['dpkg -l']

View File

@ -37,23 +37,23 @@ Examples:
}, },
{ {
"size": 56, "size": 56,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": 0, "size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": 0, "size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": 0, "size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": 1008, "size": 1008,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
... ...
] ]
@ -66,23 +66,23 @@ Examples:
}, },
{ {
"size": "56", "size": "56",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": "0", "size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": "0", "size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": "0", "size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
{ {
"size": "1008", "size": "1008",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu" "name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/..."
}, },
... ...
] ]
@ -97,9 +97,6 @@ class info():
description = '`du` command parser' description = '`du` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['du'] magic_commands = ['du']

View File

@ -1,6 +1,9 @@
"""jc - JSON CLI output utility `env` and `printenv` command output parser """jc - JSON CLI output utility `env` and `printenv` command output parser
This parser will output a list of dictionaries each containing `name` and `value` keys. If you would like a simple dictionary output, then use the `-r` command-line option or the `raw=True` argument in the `parse()` function. This parser will output a list of dictionaries each containing `name` and
`value` keys. If you would like a simple dictionary output, then use the
`-r` command-line option or the `raw=True` argument in the `parse()`
function.
Usage (cli): Usage (cli):
@ -78,8 +81,6 @@ class info():
description = '`env` command parser' description = '`env` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['env', 'printenv'] magic_commands = ['env', 'printenv']

View File

@ -53,11 +53,11 @@ Examples:
}, },
{ {
"filename": "cd_catalog.xml", "filename": "cd_catalog.xml",
"type": "XML 1.0 document text, ASCII text, with CRLF line terminators" "type": "XML 1.0 document text, ASCII text, with CRLF line ..."
}, },
{ {
"filename": "centosserial.sh", "filename": "centosserial.sh",
"type": "Bourne-Again shell script text executable, UTF-8 Unicode text" "type": "Bourne-Again shell script text executable, UTF-8 ..."
}, },
... ...
] ]
@ -72,8 +72,6 @@ class info():
description = '`file` command parser' description = '`file` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin'] compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['file'] magic_commands = ['file']

View File

@ -101,9 +101,6 @@ class info():
description = '`finger` command parser' description = '`finger` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'freebsd']
magic_commands = ['finger'] magic_commands = ['finger']
@ -179,11 +176,12 @@ def parse(data, raw=False, quiet=False):
raw_output = [] raw_output = []
if jc.utils.has_data(data): if jc.utils.has_data(data):
# Finger output is an abomination that is nearly unparsable. But there is a way: # Finger output is an abomination that is nearly unparsable. But there
# First find the location of the last character of 'Idle' in the table and cut # is a way:
# all lines at that spot. Data before that spot can use the unviversal.sparse_table_parse function. # First find the location of the last character of 'Idle' in the table
# All data after that spot can be run through regex to find the login datetime and possibly # and cut all lines at that spot. Data before that spot can use the
# other fields. # unviversal.sparse_table_parse function. All data after that spot can
# be run through regex to find the login datetime and possibly other fields.
data_lines = list(filter(None, data.splitlines())) data_lines = list(filter(None, data.splitlines()))
sep_col = data_lines[0].find('Idle') + 4 sep_col = data_lines[0].find('Idle') + 4

View File

@ -72,7 +72,8 @@ def _process(proc_data):
# process the data here # process the data here
# rebuild output for added semantic information # rebuild output for added semantic information
# use helper functions in jc.utils for int, float, bool conversions and timestamps # use helper functions in jc.utils for int, float, bool
# conversions and timestamps
return proc_data return proc_data

View File

@ -11,14 +11,16 @@ Usage (cli):
Usage (module): Usage (module):
import jc import jc
result = jc.parse('foo_s', foo_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parse('foo_s', foo_command_output.splitlines())
for item in result: for item in result:
# do something # do something
or or
import jc.parsers.foo_s import jc.parsers.foo_s
result = jc.parsers.foo_s.parse(foo_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parsers.foo_s.parse(foo_command_output.splitlines())
for item in result: for item in result:
# do something # do something
@ -26,9 +28,12 @@ Schema:
{ {
"foo": string, "foo": string,
"_jc_meta": # This object only exists if using -qq or ignore_exceptions=True
# Below object only exists if using -qq or ignore_exceptions=True
"_jc_meta":
{ {
"success": boolean, # true if successfully parsed, false if error "success": boolean, # false if error parsing
"error": string, # exists if "success" is false "error": string, # exists if "success" is false
"line": string # exists if "success" is false "line": string # exists if "success" is false
} }
@ -76,11 +81,11 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema. Dictionary. Structured data to conform to the schema.
""" """
#
# process the data here # process the data here
# rebuild output for added semantic information # rebuild output for added semantic information
# use helper functions in jc.utils for int, float, bool conversions and timestamps # use helper functions in jc.utils for int, float,
# # bool conversions and timestamps
return proc_data return proc_data
@ -91,7 +96,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
Parameters: Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True ignore_exceptions: (boolean) ignore parsing exceptions if True

View File

@ -82,8 +82,6 @@ class info():
description = '`free` command parser' description = '`free` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['free'] magic_commands = ['free']

View File

@ -94,8 +94,6 @@ class info():
description = '`/etc/fstab` file parser' description = '`/etc/fstab` file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'freebsd'] compatible = ['linux', 'freebsd']

View File

@ -118,9 +118,6 @@ class info():
description = '`/etc/group` file parser' description = '`/etc/group` file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']

View File

@ -86,9 +86,6 @@ class info():
description = '`/etc/gshadow` file parser' description = '`/etc/gshadow` file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd'] compatible = ['linux', 'aix', 'freebsd']

View File

@ -47,8 +47,6 @@ class info():
description = '`hash` command parser' description = '`hash` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']

View File

@ -78,10 +78,9 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Parses MD5 and SHA hash program output' details = 'Parses MD5 and SHA hash program output'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['md5sum', 'md5', 'shasum', 'sha1sum', 'sha224sum', 'sha256sum', 'sha384sum', 'sha512sum'] magic_commands = ['md5sum', 'md5', 'shasum', 'sha1sum', 'sha224sum',
'sha256sum', 'sha384sum', 'sha512sum']
__version__ = info.version __version__ = info.version

View File

@ -326,9 +326,6 @@ class info():
description = '`hciconfig` command parser' description = '`hciconfig` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['hciconfig'] magic_commands = ['hciconfig']
@ -351,13 +348,17 @@ def _process(proc_data):
for entry in proc_data: for entry in proc_data:
int_list = ['acl_mtu', 'acl_mtu_packets', 'sco_mtu', 'sco_mtu_packets', 'rx_bytes', 'rx_acl', 'rx_sco', int_list = ['acl_mtu', 'acl_mtu_packets', 'sco_mtu', 'sco_mtu_packets',
'rx_events', 'rx_errors', 'tx_bytes', 'tx_acl', 'tx_sco', 'tx_commands', 'tx_errors'] 'rx_bytes', 'rx_acl', 'rx_sco', 'rx_events', 'rx_errors',
'tx_bytes', 'tx_acl', 'tx_sco', 'tx_commands', 'tx_errors']
for key in entry: for key in entry:
if key in int_list: if key in int_list:
entry[key] = jc.utils.convert_to_int(entry[key]) entry[key] = jc.utils.convert_to_int(entry[key])
if 'service_classes' in entry and len(entry['service_classes']) == 1 and 'Unspecified' in entry['service_classes']: if ('service_classes' in entry and
len(entry['service_classes']) == 1 and
'Unspecified' in entry['service_classes']):
entry['service_classes'] = None entry['service_classes'] = None
return proc_data return proc_data

View File

@ -1,8 +1,12 @@
"""jc - JSON CLI output utility `history` command output parser """jc - JSON CLI output utility `history` command output parser
This parser will output a list of dictionaries each containing `line` and `command` keys. If you would like a simple dictionary output, then use the `-r` command-line option or the `raw=True` argument in the `parse()` function. This parser will output a list of dictionaries each containing `line` and
`command` keys. If you would like a simple dictionary output, then use the
`-r` command-line option or the `raw=True` argument in the `parse()`
function.
The "Magic" syntax is not supported since the `history` command is a shell builtin. The "Magic" syntax is not supported since the `history` command is a shell
builtin.
Usage (cli): Usage (cli):
@ -69,8 +73,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Optimizations by https://github.com/philippeitis' details = 'Optimizations by https://github.com/philippeitis'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']

View File

@ -83,8 +83,6 @@ class info():
description = '`/etc/hosts` file parser' description = '`/etc/hosts` file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']

View File

@ -114,9 +114,6 @@ class info():
description = '`id` command parser' description = '`id` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['id'] magic_commands = ['id']

View File

@ -198,8 +198,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Using ifconfig-parser from https://github.com/KnightWhoSayNi/ifconfig-parser' details = 'Using ifconfig-parser from https://github.com/KnightWhoSayNi/ifconfig-parser'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin'] compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['ifconfig'] magic_commands = ['ifconfig']
@ -235,10 +233,12 @@ class _IfconfigParser(object):
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
attributes = ['name', 'type', 'mac_addr', 'ipv4_addr', 'ipv4_bcast', 'ipv4_mask', 'ipv6_addr', 'ipv6_mask', attributes = [
'ipv6_scope', 'state', 'mtu', 'metric', 'rx_packets', 'rx_errors', 'rx_dropped', 'rx_overruns', 'name', 'type', 'mac_addr', 'ipv4_addr', 'ipv4_bcast', 'ipv4_mask', 'ipv6_addr',
'rx_frame', 'tx_packets', 'tx_errors', 'tx_dropped', 'tx_overruns', 'tx_carrier', 'tx_collisions', 'ipv6_mask', 'ipv6_scope', 'state', 'mtu', 'metric', 'rx_packets', 'rx_errors',
'rx_bytes', 'tx_bytes'] 'rx_dropped', 'rx_overruns', 'rx_frame', 'tx_packets', 'tx_errors', 'tx_dropped',
'tx_overruns', 'tx_carrier', 'tx_collisions', 'rx_bytes', 'tx_bytes'
]
def __init__(self, console_output): def __init__(self, console_output):
""" """
@ -436,9 +436,11 @@ def _process(proc_data):
List of Dictionaries. Structured data to conform to the schema. List of Dictionaries. Structured data to conform to the schema.
""" """
for entry in proc_data: for entry in proc_data:
int_list = ['flags', 'mtu', 'ipv6_mask', 'rx_packets', 'rx_bytes', 'rx_errors', 'rx_dropped', 'rx_overruns', int_list = [
'rx_frame', 'tx_packets', 'tx_bytes', 'tx_errors', 'tx_dropped', 'tx_overruns', 'tx_carrier', 'flags', 'mtu', 'ipv6_mask', 'rx_packets', 'rx_bytes', 'rx_errors', 'rx_dropped',
'tx_collisions', 'metric'] 'rx_overruns', 'rx_frame', 'tx_packets', 'tx_bytes', 'tx_errors', 'tx_dropped',
'tx_overruns', 'tx_carrier', 'tx_collisions', 'metric'
]
for key in entry: for key in entry:
if key in int_list: if key in int_list:
entry[key] = jc.utils.convert_to_int(entry[key]) entry[key] = jc.utils.convert_to_int(entry[key])

View File

@ -1,8 +1,12 @@
"""jc - JSON CLI output utility `INI` file parser """jc - JSON CLI output utility `INI` file parser
Parses standard `INI` files and files containing simple key/value pairs. Delimiter can be `=` or `:`. Missing values are supported. Comment prefix can be `#` or `;`. Comments must be on their own line. Parses standard `INI` files and files containing simple key/value pairs.
Delimiter can be `=` or `:`. Missing values are supported. Comment prefix
can be `#` or `;`. Comments must be on their own line.
Note: Values starting and ending with quotation marks will have the marks removed. If you would like to keep the quotation marks, use the `-r` command-line argument or the `raw=True` argument in `parse()`. Note: Values starting and ending with quotation marks will have the marks
removed. If you would like to keep the quotation marks, use the `-r`
command-line argument or the `raw=True` argument in `parse()`.
Usage (cli): Usage (cli):
@ -20,11 +24,8 @@ Usage (module):
Schema: Schema:
ini or key/value document converted to a dictionary - see configparser standard ini or key/value document converted to a dictionary - see the
library documentation for more details. configparser standard library documentation for more details.
Note: Values starting and ending with quotation marks will have the marks removed.
If you would like to keep the quotation marks, use the -r or raw=True argument.
{ {
"key1": string, "key1": string,
@ -76,8 +77,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Using configparser from the standard library' details = 'Using configparser from the standard library'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
@ -108,8 +107,12 @@ def _process(proc_data):
# simple key/value files with no headers # simple key/value files with no headers
else: else:
if proc_data[heading] is not None and proc_data[heading].startswith('"') and proc_data[heading].endswith('"'): if (proc_data[heading] is not None and
proc_data[heading].startswith('"') and
proc_data[heading].endswith('"')):
proc_data[heading] = proc_data[heading].lstrip('"').rstrip('"') proc_data[heading] = proc_data[heading].lstrip('"').rstrip('"')
elif proc_data[heading] is None: elif proc_data[heading] is None:
proc_data[heading] = '' proc_data[heading] = ''

View File

@ -11,14 +11,16 @@ Usage (cli):
Usage (module): Usage (module):
import jc import jc
result = jc.parse('iostat_s', iostat_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parse('iostat_s', iostat_command_output.splitlines())
for item in result: for item in result:
# do something # do something
or or
import jc.parsers.iostat_s import jc.parsers.iostat_s
result = jc.parsers.iostat_s.parse(iostat_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parsers.iostat_s.parse(iostat_command_output.splitlines())
for item in result: for item in result:
# do something # do something
@ -75,9 +77,12 @@ Schema:
"percent_util": float, "percent_util": float,
"percent_rrqm": float, "percent_rrqm": float,
"percent_wrqm": float, "percent_wrqm": float,
"_jc_meta": # This object only exists if using -qq or ignore_exceptions=True
# Below object only exists if using -qq or ignore_exceptions=True
"_jc_meta":
{ {
"success": boolean, # true if successfully parsed, false if error "success": boolean, # false if error parsing
"error": string, # exists if "success" is false "error": string, # exists if "success" is false
"line": string # exists if "success" is false "line": string # exists if "success" is false
} }
@ -86,13 +91,13 @@ Schema:
Examples: Examples:
$ iostat | jc --iostat-s $ iostat | jc --iostat-s
{"percent_user":0.14,"percent_nice":0.0,"percent_system":0.16,"percent_iowait":0.0,"percent_steal":0.0,"percent_idle":99.7,"type":"cpu"} {"percent_user":0.14,"percent_nice":0.0,"percent_system":0.16,...}
{"device":"sda","tps":0.24,"kb_read_s":5.28,"kb_wrtn_s":1.1,"kb_read":203305,"kb_wrtn":42368,"type":"device"} {"device":"sda","tps":0.24,"kb_read_s":5.28,"kb_wrtn_s":1.1...}
... ...
$ iostat | jc --iostat-s -r $ iostat | jc --iostat-s -r
{"percent_user":"0.14","percent_nice":"0.00","percent_system":"0.16","percent_iowait":"0.00","percent_steal":"0.00","percent_idle":"99.70","type":"cpu"} {"percent_user":"0.14","percent_nice":"0.00","percent_system":"0.16"...}
{"device":"sda","tps":"0.24","kb_read_s":"5.28","kb_wrtn_s":"1.10","kb_read":"203305","kb_wrtn":"42368","type":"device"} {"device":"sda","tps":"0.24","kb_read_s":"5.28","kb_wrtn_s":"1.10"...}
... ...
""" """
import jc.utils import jc.utils
@ -160,7 +165,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
Parameters: Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True ignore_exceptions: (boolean) ignore parsing exceptions if True

View File

@ -172,8 +172,6 @@ class info():
description = '`iptables` command parser' description = '`iptables` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['iptables'] magic_commands = ['iptables']

View File

@ -1,6 +1,7 @@
"""jc - JSON CLI output utility `iw dev <device> scan` command output parser """jc - JSON CLI output utility `iw dev <device> scan` command output parser
This parser is considered beta quality. Not all fields are parsed and there are not enough samples to test. This parser is considered beta quality. Not all fields are parsed and there
are not enough samples to test.
Usage (cli): Usage (cli):
@ -24,7 +25,7 @@ Schema:
[ [
{ {
"foo": string/integer/float, # best guess based on value "foo": string/integer/float, # best guess based on value
"bar": string/integer/float, "bar": string/integer/float,
"baz": string/integer/float "baz": string/integer/float
} }
@ -131,8 +132,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Enhancements by Philipp Schmitt (https://pschmitt.dev/)' details = 'Enhancements by Philipp Schmitt (https://pschmitt.dev/)'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['iw dev'] magic_commands = ['iw dev']
@ -325,7 +324,9 @@ def parse(data, raw=False, quiet=False):
split_line = line.split(':', maxsplit=1) split_line = line.split(':', maxsplit=1)
if len(split_line) == 2: if len(split_line) == 2:
split_line[0] = split_line[0].lower().replace('*', '').replace('(', '').replace(')', '').replace(',', '').replace('-', '_').strip().replace(' ', '_') split_line[0] = split_line[0].lower().replace('*', '').replace('(', '')\
.replace(')', '').replace(',', '').replace('-', '_')\
.strip().replace(' ', '_')
section[split_line[0]] = split_line[1].strip() section[split_line[0]] = split_line[1].strip()
continue continue

View File

@ -26,15 +26,16 @@ Schema:
Examples: Examples:
$ cat MANIFEST.MF | jc --jar-manifest -p $ cat MANIFEST.MF | jc --jar-manifest -p
$ unzip -c apache-log4j-2.16.0-bin/log4j-core-2.16.0.jar META-INF/MANIFEST.MF | jc --jar-manifest -p $ unzip -c log4j-core-2.16.0.jar META-INF/MANIFEST.MF | \\
$ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | jc --jar-manifest -p jc --jar-manifest -p
$ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | \\
jc --jar-manifest -p
$ cat MANIFEST.MF | jc --jar-manifest -p $ cat MANIFEST.MF | jc --jar-manifest -p
[ [
{ {
"Import_Package": "com.conversantmedia.util.concurrent;resolution:=optional,com.fasterxml.jackson.annotation;version=\"[2.12,3)\";resolution:=optional,com.fasterxml.jackson.core;version=\"[2.12,3)\";resolution:=optional,com.fasterxml.jackson.core.type;version=\"[2.12,3)\";resolution:=optional,com.fasterxml.jackson.cor...", "Import_Package": "com.conversantmedia.util.concurrent;resoluti...",
"Export_Package": "org.apache.logging.log4j.core;uses:=\"org.apache.logging.log4j,org.apache.logging.log4j.core.config,org.apache.logging.log4j.core.impl,org.apache.logging.log4j.core.layout,org.apache.logging.log4j.core.time,org.apache.logging.log4j.message,org.apache.logging.log4j.spi,org.apache.logging.log4j.status...", "Export_Package": "org.apache.logging.log4j.core;uses:=\"org.ap...",
"Manifest_Version": "1.0", "Manifest_Version": "1.0",
"Bundle_License": "https://www.apache.org/licenses/LICENSE-2.0.txt", "Bundle_License": "https://www.apache.org/licenses/LICENSE-2.0.txt",
"Bundle_SymbolicName": "org.apache.logging.log4j.core", "Bundle_SymbolicName": "org.apache.logging.log4j.core",
@ -47,28 +48,28 @@ Examples:
} }
] ]
$ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | jc --jar-manifest -p $ unzip -c 'apache-log4j-2.16.0-bin/*.jar' META-INF/MANIFEST.MF | \\
jc --jar-manifest -p
[ [
... ...
{ {
"Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-sources.jar", "Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-so...",
"Manifest_Version": "1.0", "Manifest_Version": "1.0",
"Built_By": "matt", "Built_By": "matt",
"Created_By": "Apache Maven 3.8.4", "Created_By": "Apache Maven 3.8.4",
"Build_Jdk": "1.8.0_312" "Build_Jdk": "1.8.0_312"
}, },
{ {
"Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-javadoc.jar", "Archive": "apache-log4j-2.16.0-bin/log4j-spring-boot-2.16.0-ja...",
"Manifest_Version": "1.0", "Manifest_Version": "1.0",
"Built_By": "matt", "Built_By": "matt",
"Created_By": "Apache Maven 3.8.4", "Created_By": "Apache Maven 3.8.4",
"Build_Jdk": "1.8.0_312" "Build_Jdk": "1.8.0_312"
}, },
{ {
"Bundle_SymbolicName": "org.apache.logging.log4j.spring-cloud-config-client.logging.log4j.core.util;version=\"[2.16,3)\",org.springframework.boot.autoconfigure.condition,org.springframework.cloud.context.environment,org.springframework.context,org.springframework.stereotype", "Bundle_SymbolicName": "org.apache.logging.log4j.spring-cloud-c...",
"Export_Package": "org.apache.logging.log4j.spring.cloud.config.controller;version=\"2.16.0\"ient", "Export_Package": "org.apache.logging.log4j.spring.cloud.config...",
"Archive": "apache-log4j-2.16.0-bin/log4j-spring-cloud-config-client-2.16.0.jar", "Archive": "apache-log4j-2.16.0-bin/log4j-spring-cloud-config-c...",
"Manifest_Version": "1.0", "Manifest_Version": "1.0",
"Bundle_License": "https://www.apache.org/licenses/LICENSE-2.0.txt", "Bundle_License": "https://www.apache.org/licenses/LICENSE-2.0.txt",
... ...

View File

@ -2,7 +2,8 @@
Also supports the `-l` option. Also supports the `-l` option.
The "Magic" syntax is not supported since the `jobs` command is a shell builtin. The "Magic" syntax is not supported since the `jobs` command is a shell
builtin.
Usage (cli): Usage (cli):
@ -102,8 +103,6 @@ class info():
description = '`jobs` command parser' description = '`jobs` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['jobs'] magic_commands = ['jobs']

View File

@ -1,8 +1,12 @@
"""jc - JSON CLI output utility `Key/Value` file parser """jc - JSON CLI output utility `Key/Value` file parser
Supports files containing simple key/value pairs. Delimiter can be `=` or `:`. Missing values are supported. Comment prefix can be `#` or `;`. Comments must be on their own line. Supports files containing simple key/value pairs. Delimiter can be `=` or
`:`. Missing values are supported. Comment prefix can be `#` or `;`.
Comments must be on their own line.
Note: Values starting and ending with quotation marks will have the marks removed. If you would like to keep the quotation marks, use the `-r` command-line argument or the `raw=True` argument in `parse()`. Note: Values starting and ending with quotation marks will have the marks
removed. If you would like to keep the quotation marks, use the `-r`
command-line argument or the `raw=True` argument in `parse()`.
Usage (cli): Usage (cli):
@ -20,7 +24,8 @@ Usage (module):
Schema: Schema:
key/value document converted to a dictionary - see configparser standard library documentation for more details. key/value document converted to a dictionary - see the
configparser standard library documentation for more details.
{ {
"key1": string, "key1": string,
@ -57,8 +62,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'This is a wrapper for the INI parser' details = 'This is a wrapper for the INI parser'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']

View File

@ -2,7 +2,9 @@
Supports `-w` and `-F` options. Supports `-w` and `-F` options.
Calculated epoch time fields are naive (i.e. based on the local time of the system the parser is run on) since there is no timezone information in the `last` command output. Calculated epoch time fields are naive (i.e. based on the local time of the
system the parser is run on) since there is no timezone information in the
`last` command output.
Usage (cli): Usage (cli):
@ -32,9 +34,9 @@ Schema:
"login": string, "login": string,
"logout": string, "logout": string,
"duration": string, "duration": string,
"login_epoch": integer, # (naive) available with last -F option "login_epoch": integer, # (naive) available with last -F option
"logout_epoch": integer, # (naive) available with last -F option "logout_epoch": integer, # (naive) available with last -F option
"duration_seconds": integer # available with last -F option "duration_seconds": integer # available with last -F option
} }
] ]
@ -114,8 +116,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Enhancements by https://github.com/zerolagtime' details = 'Enhancements by https://github.com/zerolagtime'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['last', 'lastb'] magic_commands = ['last', 'lastb']
@ -203,7 +203,10 @@ def parse(data, raw=False, quiet=False):
for entry in cleandata: for entry in cleandata:
output_line = {} output_line = {}
if entry.startswith('wtmp begins ') or entry.startswith('btmp begins ') or entry.startswith('utx.log begins '): if (entry.startswith('wtmp begins ') or
entry.startswith('btmp begins ') or
entry.startswith('utx.log begins ')):
continue continue
entry = entry.replace('system boot', 'system_boot') entry = entry.replace('system boot', 'system_boot')

View File

@ -4,11 +4,17 @@ Options supported:
- `lbaR1` - `lbaR1`
- `--time-style=full-iso` - `--time-style=full-iso`
Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly parse filenames that include newline characters. Since `ls` does not encode newlines in filenames when outputting to a pipe it will cause `jc` to see multiple files instead of a single file if `-1`, `-l`, or `-b` is not used. Alternatively, `vdir` can be used, which is the same as running `ls -lb`. Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
parse filenames that include newline characters. Since `ls` does not encode
newlines in filenames when outputting to a pipe it will cause `jc` to see
multiple files instead of a single file if `-1`, `-l`, or `-b` is not used.
Alternatively, `vdir` can be used, which is the same as running `ls -lb`.
The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `epoch` calculated timestamp field is naive. (i.e. based on the local
time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. The `epoch_utc` calculated timestamp field is timezone-aware and is only
available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -40,11 +46,14 @@ Schema:
"group": string, "group": string,
"size": integer, "size": integer,
"date": string, "date": string,
"epoch": integer, # naive timestamp if date field exists and can be converted "epoch": integer, # [0]
"epoch_utc": integer # timezone aware timestamp if date field is in UTC and can be converted "epoch_utc": integer # [1]
} }
] ]
[0] naive timestamp if date field exists and can be converted
[1] timezone aware timestamp if date field is in UTC and can be converted
Examples: Examples:
$ ls /usr/bin | jc --ls -p $ ls /usr/bin | jc --ls -p
@ -116,8 +125,6 @@ class info():
description = '`ls` command parser' description = '`ls` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['ls', 'vdir'] magic_commands = ['ls', 'vdir']

View File

@ -1,14 +1,19 @@
"""jc - JSON CLI output utility `ls` and `vdir` command output streaming parser """jc - JSON CLI output utility `ls` and `vdir` command output streaming
parser
> This streaming parser outputs JSON Lines > This streaming parser outputs JSON Lines
Requires the `-l` option to be used on `ls`. If there are newline characters in the filename, then make sure to use the `-b` option on `ls`. Requires the `-l` option to be used on `ls`. If there are newline characters
in the filename, then make sure to use the `-b` option on `ls`.
The `jc` `-qq` option can be used to ignore parsing errors. (e.g. filenames with newline characters, but `-b` was not used) The `jc` `-qq` option can be used to ignore parsing errors. (e.g. filenames
with newline characters, but `-b` was not used)
The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `epoch` calculated timestamp field is naive (i.e. based on the local time
of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. The `epoch_utc` calculated timestamp field is timezone-aware and is only
available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -17,14 +22,16 @@ Usage (cli):
Usage (module): Usage (module):
import jc import jc
result = jc.parse('ls_s', ls_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parse('ls_s', ls_command_output.splitlines())
for item in result: for item in result:
# do something # do something
or or
import jc.parsers.ls_s import jc.parsers.ls_s
result = jc.parsers.ls_s.parse(ls_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parsers.ls_s.parse(ls_command_output.splitlines())
for item in result: for item in result:
# do something # do something
@ -39,28 +46,34 @@ Schema:
"group": string, "group": string,
"size": integer, "size": integer,
"date": string, "date": string,
"epoch": integer, # naive timestamp if date field exists and can be converted "epoch": integer, # [0]
"epoch_utc": integer, # timezone aware timestamp if date field is in UTC and can be converted "epoch_utc": integer, # [1]
"_jc_meta": # This object only exists if using -qq or ignore_exceptions=True
# Below object only exists if using -qq or ignore_exceptions=True
"_jc_meta":
{ {
"success": boolean, # true if successfully parsed, false if error "success": boolean, # false if error parsing
"error": string, # exists if "success" is false "error": string, # exists if "success" is false
"line": string # exists if "success" is false "line": string # exists if "success" is false
} }
} }
[0] naive timestamp if date field exists and can be converted
[1] timezone aware timestamp if date field is in UTC and can be converted
Examples: Examples:
$ ls -l /usr/bin | jc --ls-s $ ls -l /usr/bin | jc --ls-s
{"filename":"2to3-","flags":"-rwxr-xr-x","links":4,"owner":"root","group":"wheel","size":925,"date":"Feb 22 2019"} {"filename":"2to3-","flags":"-rwxr-xr-x","links":4,"owner":"root","...}
{"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/2to3-2.7","flags":"lrwxr-xr-x","links":1,"owner":"root","group":"wheel","size":74,"date":"May 4 2019"} {"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/P...}
{"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":1,"owner":"root","group":"wheel","size":55152,"date":"May 3 2019"} {"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":1,...}
... ...
$ ls -l /usr/bin | jc --ls-s -r $ ls -l /usr/bin | jc --ls-s -r
{"filename":"2to3-","flags":"-rwxr-xr-x","links":"4","owner":"root","group":"wheel","size":"925","date":"Feb 22 2019"} {"filename":"2to3-","flags":"-rwxr-xr-x","links":"4","owner":"roo"..."}
{"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/2to3-2.7","flags":"lrwxr-xr-x","links":"1","owner":"root","group":"wheel","size":"74","date":"May 4 2019"} {"filename":"2to3-2.7","link_to":"../../System/Library/Frameworks/P...}
{"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":"1","owner":"root","group":"wheel","size":"55152","date":"May 3 2019"} {"filename":"AssetCacheLocatorUtil","flags":"-rwxr-xr-x","links":"1...}
... ...
""" """
import re import re
@ -75,8 +88,6 @@ class info():
description = '`ls` command streaming parser' description = '`ls` command streaming parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
streaming = True streaming = True
@ -117,7 +128,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
Parameters: Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True ignore_exceptions: (boolean) ignore parsing exceptions if True

View File

@ -90,7 +90,10 @@ Examples:
... ...
] ]
$ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p $ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,\\
STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,\\
SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,\\
PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p
[ [
{ {
"name": "sda", "name": "sda",
@ -179,7 +182,10 @@ Examples:
... ...
] ]
$ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p -r $ lsblk -o +KNAME,FSTYPE,LABEL,UUID,PARTLABEL,PARTUUID,RA,MODEL,SERIAL,\\
STATE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,\\
SCHED,RQ-SIZE,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO,WSAME,WWN,RAND,\\
PKNAME,HCTL,TRAN,REV,VENDOR | jc --lsblk -p -r
[ [
{ {
"name": "sda", "name": "sda",
@ -278,8 +284,6 @@ class info():
description = '`lsblk` command parser' description = '`lsblk` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['lsblk'] magic_commands = ['lsblk']
@ -302,7 +306,8 @@ def _process(proc_data):
for entry in proc_data: for entry in proc_data:
# boolean and integer changes # boolean and integer changes
bool_list = ['rm', 'ro', 'rota', 'disc_zero', 'rand'] bool_list = ['rm', 'ro', 'rota', 'disc_zero', 'rand']
int_list = ['ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec', 'rq_size', 'disc_aln'] int_list = ['ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec',
'rq_size', 'disc_aln']
for key in entry: for key in entry:
if key in bool_list: if key in bool_list:
entry[key] = jc.utils.convert_to_bool(entry[key]) entry[key] = jc.utils.convert_to_bool(entry[key])

View File

@ -135,8 +135,6 @@ class info():
description = '`lsmod` command parser' description = '`lsmod` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['lsmod'] magic_commands = ['lsmod']

View File

@ -129,8 +129,6 @@ class info():
description = '`lsof` command parser' description = '`lsof` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['lsof'] magic_commands = ['lsof']

View File

@ -22,8 +22,9 @@ Usage (module):
Schema: Schema:
Note: <item> object keynames are assigned directly from the lsusb output. Note: <item> object keynames are assigned directly from the lsusb
If there are duplicate <item> names in a section, only the last one is converted. output. If there are duplicate <item> names in a section, only the
last one is converted.
[ [
{ {

View File

@ -84,8 +84,6 @@ class info():
description = '`mount` command parser' description = '`mount` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['mount'] magic_commands = ['mount']

View File

@ -2,7 +2,8 @@
Caveats: Caveats:
- Use of multiple `l` options is not supported on OSX (e.g. `netstat -rlll`) - Use of multiple `l` options is not supported on OSX (e.g. `netstat -rlll`)
- Use of the `A` option is not supported on OSX when using the `r` option (e.g. `netstat -rA`) - Use of the `A` option is not supported on OSX when using the `r` option
(e.g. `netstat -rA`)
Usage (cli): Usage (cli):
@ -363,8 +364,6 @@ class info():
description = '`netstat` command parser' description = '`netstat` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['netstat'] magic_commands = ['netstat']
@ -386,13 +385,14 @@ def _process(proc_data):
""" """
for entry in proc_data: for entry in proc_data:
# integer and float conversions # integer and float conversions
int_list = ['recv_q', 'send_q', 'pid', 'refcnt', 'inode', 'unit', 'vendor', 'class', int_list = [
'osx_flags', 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes', 'recv_q', 'send_q', 'pid', 'refcnt', 'inode', 'unit', 'vendor', 'class', 'osx_flags',
'route_refs', 'use', 'mtu', 'mss', 'window', 'irtt', 'metric', 'ipkts', 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes', 'route_refs', 'use',
'ierrs', 'opkts', 'oerrs', 'coll', 'rx_ok', 'rx_err', 'rx_drp', 'rx_ovr', 'mtu', 'mss', 'window', 'irtt', 'metric', 'ipkts', 'ierrs', 'opkts', 'oerrs', 'coll',
'tx_ok', 'tx_err', 'tx_drp', 'tx_ovr', 'idrop', 'ibytes', 'obytes', 'r_mbuf', 'rx_ok', 'rx_err', 'rx_drp', 'rx_ovr', 'tx_ok', 'tx_err', 'tx_drp', 'tx_ovr', 'idrop',
's_mbuf', 'r_clus', 's_clus', 'r_hiwa', 's_hiwa', 'r_lowa', 's_lowa', 'r_bcnt', 'ibytes', 'obytes', 'r_mbuf', 's_mbuf', 'r_clus', 's_clus', 'r_hiwa', 's_hiwa',
's_bcnt', 'r_bmax', 's_bmax', 'rexmit', 'ooorcv', '0_win'] 'r_lowa', 's_lowa', 'r_bcnt', 's_bcnt', 'r_bmax', 's_bmax', 'rexmit', 'ooorcv', '0_win'
]
float_list = ['rexmt', 'persist', 'keep', '2msl', 'delack', 'rcvtime'] float_list = ['rexmt', 'persist', 'keep', '2msl', 'delack', 'rcvtime']
for key in entry: for key in entry:
if key in int_list: if key in int_list:

View File

@ -216,8 +216,6 @@ class info():
description = '`ntpq -p` command parser' description = '`ntpq -p` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'freebsd'] compatible = ['linux', 'freebsd']
magic_commands = ['ntpq'] magic_commands = ['ntpq']

View File

@ -103,9 +103,6 @@ class info():
description = '`/etc/passwd` file parser' description = '`/etc/passwd` file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']

View File

@ -4,7 +4,8 @@ Supports `ping` and `ping6` output.
Usage (cli): Usage (cli):
Note: Use the ping `-c` (count) option, otherwise data will not be piped to `jc`. Note: Use the ping `-c` (count) option, otherwise data will not be
piped to `jc`.
$ ping -c 3 1.2.3.4 | jc --ping $ ping -c 3 1.2.3.4 | jc --ping
@ -28,7 +29,7 @@ Schema:
"source_ip": string, "source_ip": string,
"destination_ip": string, "destination_ip": string,
"data_bytes": integer, "data_bytes": integer,
"pattern": string, # (null if not set) "pattern": string, # null if not set
"destination": string, "destination": string,
"packets_transmitted": integer, "packets_transmitted": integer,
"packets_received": integer, "packets_received": integer,
@ -40,8 +41,8 @@ Schema:
"round_trip_ms_stddev": float, "round_trip_ms_stddev": float,
"responses": [ "responses": [
{ {
"type": string, # 'reply', 'timeout', 'unparsable_line', etc. See `_error_type.type_map` for all options "type": string, # [0]
"unparsed_line": string, # only if an 'unparsable_line' type "unparsed_line": string, # [1]
"timestamp": float, "timestamp": float,
"bytes": integer, "bytes": integer,
"response_ip": string, "response_ip": string,
@ -49,21 +50,26 @@ Schema:
"ttl": integer, "ttl": integer,
"time_ms": float, "time_ms": float,
"duplicate": boolean, "duplicate": boolean,
"vr": integer, # hex value converted to decimal "vr": integer, # [2]
"hl": integer, # hex value converted to decimal "hl": integer, # [2]
"tos": integer, # hex value converted to decimal "tos": integer, # [2]
"len": integer, # hex value converted to decimal "len": integer, # [2]
"id": integer, # hex value converted to decimal "id": integer, # [2]
"flg": integer, # hex value converted to decimal "flg": integer, # [2]
"off": integer, # hex value converted to decimal "off": integer, # [2]
"pro": integer, # hex value converted to decimal "pro": integer, # [2]
"cks": ingeger, # hex value converted to decimal "cks": ingeger, # [2]
"src": string, "src": string,
"dst": string "dst": string
} }
] ]
} }
[0] 'reply', 'timeout', 'unparsable_line', etc. See
`_error_type.type_map` for all options
[1] only if an 'unparsable_line' type
[2] hex value converted to decimal
Examples: Examples:
$ ping -c 3 -p ff cnn.com | jc --ping -p $ ping -c 3 -p ff cnn.com | jc --ping -p
@ -167,8 +173,6 @@ class info():
description = '`ping` and `ping6` command parser' description = '`ping` and `ping6` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['ping', 'ping6'] magic_commands = ['ping', 'ping6']
@ -188,10 +192,14 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema. Dictionary. Structured data to conform to the schema.
""" """
int_list = ['data_bytes', 'packets_transmitted', 'packets_received', 'bytes', 'icmp_seq', 'ttl', int_list = [
'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'] 'data_bytes', 'packets_transmitted', 'packets_received', 'bytes', 'icmp_seq', 'ttl',
float_list = ['packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max', 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'
'round_trip_ms_stddev', 'timestamp', 'time_ms'] ]
float_list = [
'packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max',
'round_trip_ms_stddev', 'timestamp', 'time_ms'
]
for key in proc_data: for key in proc_data:
if key in int_list: if key in int_list:

View File

@ -8,66 +8,79 @@ Usage (cli):
$ ping | jc --ping-s $ ping | jc --ping-s
> Note: When piping `jc` converted `ping` output to other processes it may appear the output is hanging due to the OS pipe buffers. This is because `ping` output is too small to quickly fill up the buffer. Use the `-u` option to unbuffer the `jc` output if you would like immediate output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output) for more information. > Note: When piping `jc` converted `ping` output to other processes it may
appear the output is hanging due to the OS pipe buffers. This is because
`ping` output is too small to quickly fill up the buffer. Use the `-u`
option to unbuffer the `jc` output if you would like immediate output.
See the[readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
for more information.
Usage (module): Usage (module):
import jc import jc
result = jc.parse('ping_s', ping_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parse('ping_s', ping_command_output.splitlines())
for item in result: for item in result:
# do something # do something
or or
import jc.parsers.ping_s import jc.parsers.ping_s
result = jc.parsers.ping_s.parse(ping_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parsers.ping_s.parse(ping_command_output.splitlines())
for item in result: for item in result:
# do something # do something
Schema: Schema:
{ {
"type": string, # 'reply', 'timeout', 'summary', etc. See `_error_type.type_map` for all options. "type": string, # [0]
"source_ip": string, "source_ip": string,
"destination_ip": string, "destination_ip": string,
"sent_bytes": integer, "sent_bytes": integer,
"pattern": string, # (null if not set) "pattern": string, # (null if not set)
"destination": string, "destination": string,
"timestamp": float, "timestamp": float,
"response_bytes": integer, "response_bytes": integer,
"response_ip": string, "response_ip": string,
"icmp_seq": integer, "icmp_seq": integer,
"ttl": integer, "ttl": integer,
"time_ms": float, "time_ms": float,
"duplicate": boolean, "duplicate": boolean,
"packets_transmitted": integer, "packets_transmitted": integer,
"packets_received": integer, "packets_received": integer,
"packet_loss_percent": float, "packet_loss_percent": float,
"duplicates": integer, "duplicates": integer,
"round_trip_ms_min": float, "round_trip_ms_min": float,
"round_trip_ms_avg": float, "round_trip_ms_avg": float,
"round_trip_ms_max": float, "round_trip_ms_max": float,
"round_trip_ms_stddev": float, "round_trip_ms_stddev": float,
"_jc_meta": # This object only exists if using -qq or ignore_exceptions=True
# Below object only exists if using -qq or ignore_exceptions=True
"_jc_meta":
{ {
"success": boolean, # true if successfully parsed, false if error "success": boolean, # false if error parsing
"error": string, # exists if "success" is false "error": string, # exists if "success" is false
"line": string # exists if "success" is false "line": string # exists if "success" is false
} }
} }
[0] 'reply', 'timeout', 'summary', etc. See `_error_type.type_map`
for all options.
Examples: Examples:
$ ping 1.1.1.1 | jc --ping-s $ ping 1.1.1.1 | jc --ping-s
{"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"1.1.1.1","icmp_seq":0,"ttl":56,"time_ms":23.703} {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"patte...}
{"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"1.1.1.1","icmp_seq":1,"ttl":56,"time_ms":22.862} {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"patte...}
{"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"pattern":null,"response_bytes":64,"response_ip":"1.1.1.1","icmp_seq":2,"ttl":56,"time_ms":22.82} {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":56,"patte...}
... ...
$ ping 1.1.1.1 | jc --ping-s -r $ ping 1.1.1.1 | jc --ping-s -r
{"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","pattern":null,"response_bytes":"64","response_ip":"1.1.1.1","icmp_seq":"0","ttl":"56","time_ms":"23.054"} {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","patte...}
{"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","pattern":null,"response_bytes":"64","response_ip":"1.1.1.1","icmp_seq":"1","ttl":"56","time_ms":"24.739"} {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","patte...}
{"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","pattern":null,"response_bytes":"64","response_ip":"1.1.1.1","icmp_seq":"2","ttl":"56","time_ms":"23.232"} {"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","patte...}
... ...
""" """
import string import string
@ -83,8 +96,6 @@ class info():
description = '`ping` and `ping6` command streaming parser' description = '`ping` and `ping6` command streaming parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
streaming = True streaming = True
@ -104,10 +115,14 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema. Dictionary. Structured data to conform to the schema.
""" """
int_list = ['sent_bytes', 'packets_transmitted', 'packets_received', 'response_bytes', 'icmp_seq', 'ttl', int_list = [
'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'] 'sent_bytes', 'packets_transmitted', 'packets_received', 'response_bytes', 'icmp_seq',
float_list = ['packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max', 'ttl', 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'
'round_trip_ms_stddev', 'timestamp', 'time_ms'] ]
float_list = [
'packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max',
'round_trip_ms_stddev', 'timestamp', 'time_ms'
]
for key in proc_data: for key in proc_data:
if key in int_list: if key in int_list:
@ -460,7 +475,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
Parameters: Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True ignore_exceptions: (boolean) ignore parsing exceptions if True

View File

@ -57,8 +57,6 @@ class info():
description = '`pip list` command parser' description = '`pip list` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['pip list', 'pip3 list'] magic_commands = ['pip list', 'pip3 list']

View File

@ -74,8 +74,6 @@ class info():
description = '`pip show` command parser' description = '`pip show` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['pip show', 'pip3 show'] magic_commands = ['pip show', 'pip3 show']

View File

@ -58,7 +58,7 @@ Examples:
"stime": "Nov01", "stime": "Nov01",
"tty": null, "tty": null,
"time": "00:00:11", "time": "00:00:11",
"cmd": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" "cmd": "/usr/lib/systemd/systemd --switched-root --system --dese..."
}, },
{ {
"uid": "root", "uid": "root",
@ -93,7 +93,7 @@ Examples:
"stime": "Nov01", "stime": "Nov01",
"tty": "?", "tty": "?",
"time": "00:00:11", "time": "00:00:11",
"cmd": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" "cmd": "/usr/lib/systemd/systemd --switched-root --system --dese..."
}, },
{ {
"uid": "root", "uid": "root",
@ -131,7 +131,7 @@ Examples:
"stat": "Ss", "stat": "Ss",
"start": "Nov09", "start": "Nov09",
"time": "0:08", "time": "0:08",
"command": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" "command": "/usr/lib/systemd/systemd --switched-root --system --..."
}, },
{ {
"user": "root", "user": "root",
@ -175,7 +175,7 @@ Examples:
"stat": "Ss", "stat": "Ss",
"start": "Nov09", "start": "Nov09",
"time": "0:08", "time": "0:08",
"command": "/usr/lib/systemd/systemd --switched-root --system --deserialize 22" "command": "/usr/lib/systemd/systemd --switched-root --system --..."
}, },
{ {
"user": "root", "user": "root",
@ -216,8 +216,6 @@ class info():
description = '`ps` command parser' description = '`ps` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['ps'] magic_commands = ['ps']

View File

@ -118,8 +118,6 @@ class info():
description = '`route` command parser' description = '`route` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['route'] magic_commands = ['route']
@ -197,7 +195,9 @@ def parse(data, raw=False, quiet=False):
# fixup header row for ipv6 # fixup header row for ipv6
if ' Next Hop ' in cleandata[0]: if ' Next Hop ' in cleandata[0]:
cleandata[0] = cleandata[0].replace(' If', ' Iface') cleandata[0] = cleandata[0].replace(' If', ' Iface')
cleandata[0] = cleandata[0].replace(' Next Hop ', ' Next_Hop ').replace(' Flag ', ' Flags ').replace(' Met ', ' Metric ') cleandata[0] = cleandata[0].replace(' Next Hop ', ' Next_Hop ')\
.replace(' Flag ', ' Flags ')\
.replace(' Met ', ' Metric ')
cleandata[0] = cleandata[0].lower() cleandata[0] = cleandata[0].lower()
raw_output = jc.parsers.universal.simple_table_parse(cleandata) raw_output = jc.parsers.universal.simple_table_parse(cleandata)

View File

@ -2,9 +2,11 @@
Works with `rpm -qi [package]` or `rpm -qia`. Works with `rpm -qi [package]` or `rpm -qia`.
The `..._epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on) The `..._epoch` calculated timestamp fields are naive. (i.e. based on the
local time of the system the parser is run on)
The `..._epoch_utc` calculated timestamp fields are timezone-aware and is only available if the timezone field is UTC. The `..._epoch_utc` calculated timestamp fields are timezone-aware and is
only available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -34,16 +36,16 @@ Schema:
"release": string, "release": string,
"architecture": string, "architecture": string,
"install_date": string, "install_date": string,
"install_date_epoch": integer, # naive timestamp "install_date_epoch": integer, # [0]
"install_date_epoch_utc": integer, # Aware timestamp if timezone is UTC "install_date_epoch_utc": integer, # [1]
"group": string, "group": string,
"size": integer, "size": integer,
"license": string, "license": string,
"signature": string, "signature": string,
"source_rpm": string, "source_rpm": string,
"build_date": string, "build_date": string,
"build_epoch": integer, # naive timestamp "build_epoch": integer, # [0]
"build_epoch_utc": integer, # Aware timestamp if timezone is UTC "build_epoch_utc": integer, # [1]
"build_host": string, "build_host": string,
"relocations": string, "relocations": string,
"packager": string, "packager": string,
@ -54,6 +56,9 @@ Schema:
} }
] ]
[0] naive timestamp
[1] Aware timestamp if timezone is UTC
Examples: Examples:
$ rpm -qia | jc --rpm-qi -p $ rpm -qia | jc --rpm-qi -p
@ -68,7 +73,7 @@ Examples:
"group": "Development/Tools", "group": "Development/Tools",
"size": 1160660, "size": 1160660,
"license": "GPLv2+", "license": "GPLv2+",
"signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ID 24c6a8a7f4a80eb5", "signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ...",
"source_rpm": "make-3.82-24.el7.src.rpm", "source_rpm": "make-3.82-24.el7.src.rpm",
"build_date": "Thu 08 Aug 2019 05:47:25 PM PDT", "build_date": "Thu 08 Aug 2019 05:47:25 PM PDT",
"build_host": "x86-01.bsys.centos.org", "build_host": "x86-01.bsys.centos.org",
@ -76,8 +81,8 @@ Examples:
"packager": "CentOS BuildSystem <http://bugs.centos.org>", "packager": "CentOS BuildSystem <http://bugs.centos.org>",
"vendor": "CentOS", "vendor": "CentOS",
"url": "http://www.gnu.org/software/make/", "url": "http://www.gnu.org/software/make/",
"summary": "A GNU tool which simplifies the build process for users", "summary": "A GNU tool which simplifies the build process for ...",
"description": "A GNU tool for controlling the generation of executables and other...", "description": "A GNU tool for controlling the generation of ex...",
"build_epoch": 1565311645, "build_epoch": 1565311645,
"build_epoch_utc": null, "build_epoch_utc": null,
"install_date_epoch": 1571242902, "install_date_epoch": 1571242902,
@ -92,7 +97,7 @@ Examples:
"group": "System Environment/Base", "group": "System Environment/Base",
"size": 503608, "size": 503608,
"license": "GPLv2+", "license": "GPLv2+",
"signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ID 24c6a8a7f4a80eb5", "signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ...",
"source_rpm": "kbd-1.15.5-15.el7.src.rpm", "source_rpm": "kbd-1.15.5-15.el7.src.rpm",
"build_date": "Tue 30 Oct 2018 03:40:00 PM PDT", "build_date": "Tue 30 Oct 2018 03:40:00 PM PDT",
"build_host": "x86-01.bsys.centos.org", "build_host": "x86-01.bsys.centos.org",
@ -101,7 +106,7 @@ Examples:
"vendor": "CentOS", "vendor": "CentOS",
"url": "http://ftp.altlinux.org/pub/people/legion/kbd", "url": "http://ftp.altlinux.org/pub/people/legion/kbd",
"summary": "Legacy data for kbd package", "summary": "Legacy data for kbd package",
"description": "The kbd-legacy package contains original keymaps for kbd package...", "description": "The kbd-legacy package contains original keymap...",
"build_epoch": 1540939200, "build_epoch": 1540939200,
"build_epoch_utc": null, "build_epoch_utc": null,
"install_date_epoch": 1565891588, "install_date_epoch": 1565891588,
@ -122,7 +127,7 @@ Examples:
"group": "Development/Tools", "group": "Development/Tools",
"size": "1160660", "size": "1160660",
"license": "GPLv2+", "license": "GPLv2+",
"signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ID 24c6a8a7f4a80eb5", "signature": "RSA/SHA256, Thu 22 Aug 2019 02:34:59 PM PDT, Key ...",
"source_rpm": "make-3.82-24.el7.src.rpm", "source_rpm": "make-3.82-24.el7.src.rpm",
"build_date": "Thu 08 Aug 2019 05:47:25 PM PDT", "build_date": "Thu 08 Aug 2019 05:47:25 PM PDT",
"build_host": "x86-01.bsys.centos.org", "build_host": "x86-01.bsys.centos.org",
@ -130,8 +135,8 @@ Examples:
"packager": "CentOS BuildSystem <http://bugs.centos.org>", "packager": "CentOS BuildSystem <http://bugs.centos.org>",
"vendor": "CentOS", "vendor": "CentOS",
"url": "http://www.gnu.org/software/make/", "url": "http://www.gnu.org/software/make/",
"summary": "A GNU tool which simplifies the build process for users", "summary": "A GNU tool which simplifies the build process for...",
"description": "A GNU tool for controlling the generation of executables and other..." "description": "A GNU tool for controlling the generation of exe..."
}, },
{ {
"name": "kbd-legacy", "name": "kbd-legacy",
@ -142,7 +147,7 @@ Examples:
"group": "System Environment/Base", "group": "System Environment/Base",
"size": "503608", "size": "503608",
"license": "GPLv2+", "license": "GPLv2+",
"signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ID 24c6a8a7f4a80eb5", "signature": "RSA/SHA256, Mon 12 Nov 2018 07:17:49 AM PST, Key ...",
"source_rpm": "kbd-1.15.5-15.el7.src.rpm", "source_rpm": "kbd-1.15.5-15.el7.src.rpm",
"build_date": "Tue 30 Oct 2018 03:40:00 PM PDT", "build_date": "Tue 30 Oct 2018 03:40:00 PM PDT",
"build_host": "x86-01.bsys.centos.org", "build_host": "x86-01.bsys.centos.org",
@ -151,7 +156,7 @@ Examples:
"vendor": "CentOS", "vendor": "CentOS",
"url": "http://ftp.altlinux.org/pub/people/legion/kbd", "url": "http://ftp.altlinux.org/pub/people/legion/kbd",
"summary": "Legacy data for kbd package", "summary": "Legacy data for kbd package",
"description": "The kbd-legacy package contains original keymaps for kbd package..." "description": "The kbd-legacy package contains original keymaps..."
}, },
... ...
] ]
@ -165,9 +170,6 @@ class info():
description = '`rpm -qi` command parser' description = '`rpm -qi` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['rpm -qi', 'rpm -qia', 'rpm -qai'] magic_commands = ['rpm -qi', 'rpm -qia', 'rpm -qai']

View File

@ -55,7 +55,7 @@ Schema:
"boot": boolean, "boot": boolean,
"start": integer, "start": integer,
"end": integer, "end": integer,
"size": string, # Note: will be integer when using deprecated -d sfdisk option "size": string, # [0]
"cyls": integer, "cyls": integer,
"mib": integer, "mib": integer,
"blocks": integer, "blocks": integer,
@ -68,6 +68,8 @@ Schema:
} }
] ]
[0] will be integer when using deprecated -d sfdisk option
Examples: Examples:
# sfdisk -l | jc --sfdisk -p # sfdisk -l | jc --sfdisk -p
@ -77,7 +79,7 @@ Examples:
"cylinders": 2610, "cylinders": 2610,
"heads": 255, "heads": 255,
"sectors_per_track": 63, "sectors_per_track": 63,
"units": "cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0", "units": "cylinders of 8225280 bytes, blocks of 1024 bytes, ...",
"partitions": [ "partitions": [
{ {
"device": "/dev/sda1", "device": "/dev/sda1",
@ -142,7 +144,7 @@ Examples:
"cylinders": "2610", "cylinders": "2610",
"heads": "255", "heads": "255",
"sectors_per_track": "63", "sectors_per_track": "63",
"units": "cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0", "units": "cylinders of 8225280 bytes, blocks of 1024 bytes, co...",
"partitions": [ "partitions": [
{ {
"device": "/dev/sda1", "device": "/dev/sda1",
@ -229,9 +231,11 @@ def _process(proc_data):
List of Dictionaries. Structured to conform to the schema. List of Dictionaries. Structured to conform to the schema.
""" """
int_list = ['cylinders', 'heads', 'sectors_per_track', 'start', 'end', 'cyls', 'mib', int_list = [
'blocks', 'sectors', 'bytes', 'logical_sector_size', 'physical_sector_size', 'cylinders', 'heads', 'sectors_per_track', 'start', 'end', 'cyls', 'mib', 'blocks',
'min_io_size', 'optimal_io_size', 'free_bytes', 'free_sectors'] 'sectors', 'bytes', 'logical_sector_size', 'physical_sector_size', 'min_io_size',
'optimal_io_size', 'free_bytes', 'free_sectors'
]
bool_list = ['boot'] bool_list = ['boot']
for entry in proc_data: for entry in proc_data:

View File

@ -110,9 +110,6 @@ class info():
description = '`/etc/shadow` file parser' description = '`/etc/shadow` file parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'aix', 'freebsd']

View File

@ -1,6 +1,7 @@
"""jc - JSON CLI output utility `ss` command output parser """jc - JSON CLI output utility `ss` command output parser
Extended information options like -e and -p are not supported and may cause parsing irregularities. Extended information options like -e and -p are not supported and may cause
parsing irregularities.
Usage (cli): Usage (cli):
@ -22,7 +23,8 @@ Usage (module):
Schema: Schema:
Information from https://www.cyberciti.biz/files/ss.html used to define field names Information from https://www.cyberciti.biz/files/ss.html used to define
field names
[ [
{ {
@ -288,8 +290,6 @@ class info():
description = '`ss` command parser' description = '`ss` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['ss'] magic_commands = ['ss']

View File

@ -1,8 +1,10 @@
"""jc - JSON CLI output utility `stat` command output parser """jc - JSON CLI output utility `stat` command output parser
The `xxx_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on) The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the
local time of the system the parser is run on)
The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC. The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are
only available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -178,8 +180,6 @@ class info():
description = '`stat` command parser' description = '`stat` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['stat'] magic_commands = ['stat']
@ -200,8 +200,8 @@ def _process(proc_data):
List of Dictionaries. Structured data to conform to the schema. List of Dictionaries. Structured data to conform to the schema.
""" """
for entry in proc_data: for entry in proc_data:
int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', 'unix_device', int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid',
'rdev', 'block_size'] 'unix_device', 'rdev', 'block_size']
for key in entry: for key in entry:
if key in int_list: if key in int_list:
entry[key] = jc.utils.convert_to_int(entry[key]) entry[key] = jc.utils.convert_to_int(entry[key])

View File

@ -2,9 +2,11 @@
> This streaming parser outputs JSON Lines > This streaming parser outputs JSON Lines
The `xxx_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on). The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the
local time of the system the parser is run on).
The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC. The `xxx_epoch_utc` calculated timestamp fields are timezone-aware and are
only available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -13,14 +15,16 @@ Usage (cli):
Usage (module): Usage (module):
import jc import jc
result = jc.parse('stat_s', stat_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parse('stat_s', stat_command_output.splitlines())
for item in result: for item in result:
# do something # do something
or or
import jc.parsers.stat_s import jc.parsers.stat_s
result = jc.parsers.stat_s.parse(stat_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parsers.stat_s.parse(stat_command_output.splitlines())
for item in result: for item in result:
# do something # do something
@ -58,9 +62,12 @@ Schema:
"rdev": integer, "rdev": integer,
"block_size": integer, "block_size": integer,
"unix_flags": string, "unix_flags": string,
"_jc_meta": # This object only exists if using -qq or ignore_exceptions=True
# Below object only exists if using -qq or ignore_exceptions=True
"_jc_meta":
{ {
"success": boolean, # true if successfully parsed, false if error "success": boolean, # false if error parsing
"error": string, # exists if "success" is false "error": string, # exists if "success" is false
"line": string # exists if "success" is false "line": string # exists if "success" is false
} }
@ -69,10 +76,10 @@ Schema:
Examples: Examples:
$ stat | jc --stat-s $ stat | jc --stat-s
{"file":"(stdin)","unix_device":1027739696,"inode":1155,"flags":"crw--w----","links":1,"user":"kbrazil","group":"tty","rdev":268435456,"size":0,"access_time":"Jan 4 15:27:44 2022","modify_time":"Jan 4 15:27:44 2022","change_time":"Jan 4 15:27:44 2022","birth_time":"Dec 31 16:00:00 1969","block_size":131072,"blocks":0,"unix_flags":"0","access_time_epoch":1641338864,"access_time_epoch_utc":null,"modify_time_epoch":1641338864,"modify_time_epoch_utc":null,"change_time_epoch":1641338864,"change_time_epoch_utc":null,"birth_time_epoch":null,"birth_time_epoch_utc":null} {"file":"(stdin)","unix_device":1027739696,"inode":1155,"flags":"cr...}
$ stat | jc --stat-s -r $ stat | jc --stat-s -r
{"file":"(stdin)","unix_device":"1027739696","inode":"1155","flags":"crw--w----","links":"1","user":"kbrazil","group":"tty","rdev":"268435456","size":"0","access_time":"Jan 4 15:28:08 2022","modify_time":"Jan 4 15:28:08 2022","change_time":"Jan 4 15:28:08 2022","birth_time":"Dec 31 16:00:00 1969","block_size":"131072","blocks":"0","unix_flags":"0"} {"file":"(stdin)","unix_device":"1027739696","inode":"1155","flag...}
""" """
import shlex import shlex
import jc.utils import jc.utils
@ -105,8 +112,8 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema. Dictionary. Structured data to conform to the schema.
""" """
int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', 'unix_device', int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid',
'rdev', 'block_size'] 'unix_device', 'rdev', 'block_size']
for key in proc_data: for key in proc_data:
if key in int_list: if key in int_list:
proc_data[key] = jc.utils.convert_to_int(proc_data[key]) proc_data[key] = jc.utils.convert_to_int(proc_data[key])
@ -129,7 +136,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
Parameters: Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True ignore_exceptions: (boolean) ignore parsing exceptions if True

View File

@ -1,6 +1,9 @@
"""jc - JSON CLI output utility `sysctl -a` command output parser """jc - JSON CLI output utility `sysctl -a` command output parser
Note: Since `sysctl` output is not easily parsable only a very simple key/value object will be output. An attempt is made to convert obvious integers and floats. If no conversion is desired, use the `-r` command-line argument or the `raw=True` argument in `parse()`. Note: Since `sysctl` output is not easily parsable only a very simple
key/value object will be output. An attempt is made to convert obvious
integers and floats. If no conversion is desired, use the `-r`
command-line argument or the `raw=True` argument in `parse()`.
Usage (cli): Usage (cli):
@ -23,7 +26,7 @@ Usage (module):
Schema: Schema:
{ {
"key1": string/integer/float, # best guess based on value "key1": string/integer/float, # best guess based on value
"key2": string/integer/float, "key2": string/integer/float,
"key3": string/integer/float "key3": string/integer/float
} }
@ -63,9 +66,6 @@ class info():
description = '`sysctl` command parser' description = '`sysctl` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['sysctl'] magic_commands = ['sysctl']

View File

@ -39,14 +39,14 @@ Examples:
"load": "loaded", "load": "loaded",
"active": "active", "active": "active",
"sub": "waiting", "sub": "waiting",
"description": "Arbitrary Executable File Formats File System Automount Point" "description": "Arbitrary Executable File Formats File System ..."
}, },
{ {
"unit": "dev-block-8:2.device", "unit": "dev-block-8:2.device",
"load": "loaded", "load": "loaded",
"active": "active", "active": "active",
"sub": "plugged", "sub": "plugged",
"description": "LVM PV 3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM on /dev/sda2 2" "description": "LVM PV 3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM o..."
}, },
{ {
"unit": "dev-cdrom.device", "unit": "dev-cdrom.device",
@ -67,8 +67,6 @@ class info():
description = '`systemctl` command parser' description = '`systemctl` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['systemctl'] magic_commands = ['systemctl']

View File

@ -84,8 +84,6 @@ class info():
description = '`systemctl list-jobs` command parser' description = '`systemctl list-jobs` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['systemctl list-jobs'] magic_commands = ['systemctl list-jobs']

View File

@ -1,4 +1,5 @@
"""jc - JSON CLI output utility `systemctl list-sockets` command output parser """jc - JSON CLI output utility `systemctl list-sockets` command output
parser
Usage (cli): Usage (cli):
@ -59,8 +60,6 @@ class info():
description = '`systemctl list-sockets` command parser' description = '`systemctl list-sockets` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['systemctl list-sockets'] magic_commands = ['systemctl list-sockets']

View File

@ -1,4 +1,5 @@
"""jc - JSON CLI output utility `systemctl list-unit-files` command output parser """jc - JSON CLI output utility `systemctl list-unit-files` command output
parser
Usage (cli): Usage (cli):
@ -55,8 +56,6 @@ class info():
description = '`systemctl list-unit-files` command parser' description = '`systemctl list-unit-files` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['systemctl list-unit-files'] magic_commands = ['systemctl list-unit-files']

View File

@ -2,9 +2,13 @@
Blank or missing elements are set to `null`. Blank or missing elements are set to `null`.
The `original_install_date_epoch` and `system_boot_time_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on) The `original_install_date_epoch` and `system_boot_time_epoch` calculated
timestamp fields are naive. (i.e. based on the local time of the system the
parser is run on)
The `original_install_date_epoch_utc` and `system_boot_time_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC. The `original_install_date_epoch_utc` and `system_boot_time_epoch_utc`
calculated timestamp fields are timezone-aware and are only available if
the timezone field is UTC.
Usage (cli): Usage (cli):
@ -33,11 +37,11 @@ Schema:
"registered_organization": string, "registered_organization": string,
"product_id": string, "product_id": string,
"original_install_date": string, "original_install_date": string,
"original_install_date_epoch": integer, # naive timestamp "original_install_date_epoch": integer, # [0]
"original_install_date_epoch_utc": integer, # timezone-aware timestamp "original_install_date_epoch_utc": integer, # [1]
"system_boot_time": string, "system_boot_time": string,
"system_boot_time_epoch": integer, # naive timestamp "system_boot_time_epoch": integer, # [0]
"system_boot_time_epoch_utc": integer, # timezone-aware timestamp "system_boot_time_epoch_utc": integer, # [1]
"system_manufacturer": string, "system_manufacturer": string,
"system_model": string, "system_model": string,
"system_type": string, "system_type": string,
@ -82,6 +86,9 @@ Schema:
} }
} }
[0] naive timestamp
[1] timezone-aware timestamp
Examples: Examples:
$ systeminfo | jc --systeminfo -p $ systeminfo | jc --systeminfo -p
@ -214,9 +221,6 @@ class info:
description = "`systeminfo` command parser" description = "`systeminfo` command parser"
author = "Jon Smith" author = "Jon Smith"
author_email = "jon@rebelliondefense.com" author_email = "jon@rebelliondefense.com"
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ["win32"] compatible = ["win32"]
magic_commands = ["systeminfo"] magic_commands = ["systeminfo"]
@ -234,11 +238,12 @@ def _process(proc_data):
Returns: Returns:
Dictionary. Some keys are optional. Example: a system without hyper-v capabilities Dictionary. Structured data to conform to the schema.
will not have a 'hyperv_requirements' key, and a system already running hyper-v
will have an empty "hyperv_requirements" object.
Structured data to conform to the schema. Some keys are optional. For example, a system without
hyper-v capabilities will not have a 'hyperv_requirements' key, and
a system already running hyper-v will have an empty
"hyperv_requirements" object.
""" """
# convert empty strings to None/null # convert empty strings to None/null
for item in proc_data: for item in proc_data:

View File

@ -1,14 +1,18 @@
"""jc - JSON CLI output utility `/usr/bin/time` command output parser """jc - JSON CLI output utility `/usr/bin/time` command output parser
Output from `/usr/bin/time` is sent to `STDERR`, so the `-o` option can be used to redirect the output to a file that can be read by `jc`. Output from `/usr/bin/time` is sent to `STDERR`, so the `-o` option can be
used to redirect the output to a file that can be read by `jc`.
Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT` so `jc` can receive it. Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT`
so `jc` can receive it.
Note: `/usr/bin/time` is similar but different from the Bash builtin `time` command. Note: `/usr/bin/time` is similar but different from the Bash builtin
`time` command.
Usage (cli): Usage (cli):
$ /usr/bin/time -o timefile.out sleep 2.5; cat timefile.out | jc --time -p $ /usr/bin/time -o timefile.out sleep 2; cat timefile.out | \\
jc --time -p
Usage (module): Usage (module):
@ -41,8 +45,8 @@ Schema:
"average_unshared_stack_size": integer, "average_unshared_stack_size": integer,
"average_shared_memory_size": integer, "average_shared_memory_size": integer,
"maximum_resident_set_size": integer, "maximum_resident_set_size": integer,
"block_input_operations": integer, # aka File system inputs "block_input_operations": integer, # [0]
"block_output_operations": integer, # aka File system outputs "block_output_operations": integer, # [1]
"major_pagefaults": integer, "major_pagefaults": integer,
"minor_pagefaults": integer, "minor_pagefaults": integer,
"swaps": integer, "swaps": integer,
@ -62,15 +66,19 @@ Schema:
"exit_status": integer "exit_status": integer
} }
[0] aka File system inputs
[1] aka File system outputs
Examples: Examples:
$ /usr/bin/time --verbose -o timefile.out sleep 2.5; cat timefile.out | jc --time -p $ /usr/bin/time --verbose -o timefile.out sleep 2; cat timefile.out | \\
jc --time -p
{ {
"command_being_timed": "sleep 2.5", "command_being_timed": "sleep 2",
"user_time": 0.0, "user_time": 0.0,
"system_time": 0.0, "system_time": 0.0,
"cpu_percent": 0, "cpu_percent": 0,
"elapsed_time": "0:02.50", "elapsed_time": "0:02.00",
"average_shared_text_size": 0, "average_shared_text_size": 0,
"average_unshared_data_size": 0, "average_unshared_data_size": 0,
"average_stack_size": 0, "average_stack_size": 0,
@ -96,13 +104,14 @@ Examples:
"elapsed_time_total_seconds": 2.5 "elapsed_time_total_seconds": 2.5
} }
$ /usr/bin/time --verbose -o timefile.out sleep 2.5; cat timefile.out | jc --time -p -r $ /usr/bin/time --verbose -o timefile.out sleep 2; cat timefile.out | \\
jc --time -p -r
{ {
"command_being_timed": "\"sleep 2.5\"", "command_being_timed": "\"sleep 2\"",
"user_time": "0.00", "user_time": "0.00",
"system_time": "0.00", "system_time": "0.00",
"cpu_percent": "0", "cpu_percent": "0",
"elapsed_time": "0:02.50", "elapsed_time": "0:02.00",
"average_shared_text_size": "0", "average_shared_text_size": "0",
"average_unshared_data_size": "0", "average_unshared_data_size": "0",
"average_stack_size": "0", "average_stack_size": "0",
@ -132,9 +141,6 @@ class info():
description = '`/usr/bin/time` command parser' description = '`/usr/bin/time` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
@ -173,12 +179,15 @@ def _process(proc_data):
(proc_data['elapsed_time_centiseconds'] / 100) (proc_data['elapsed_time_centiseconds'] / 100)
# convert ints and floats # convert ints and floats
int_list = ['cpu_percent', 'average_shared_text_size', 'average_unshared_data_size', 'average_unshared_stack_size', int_list = [
'average_shared_memory_size', 'maximum_resident_set_size', 'block_input_operations', 'cpu_percent', 'average_shared_text_size', 'average_unshared_data_size',
'block_output_operations', 'major_pagefaults', 'minor_pagefaults', 'swaps', 'page_reclaims', 'average_unshared_stack_size', 'average_shared_memory_size', 'maximum_resident_set_size',
'page_faults', 'messages_sent', 'messages_received', 'signals_received', 'voluntary_context_switches', 'block_input_operations', 'block_output_operations', 'major_pagefaults', 'minor_pagefaults',
'involuntary_context_switches', 'average_stack_size', 'average_total_size', 'average_resident_set_size', 'swaps', 'page_reclaims', 'page_faults', 'messages_sent', 'messages_received',
'signals_delivered', 'page_size', 'exit_status'] 'signals_received', 'voluntary_context_switches', 'involuntary_context_switches',
'average_stack_size', 'average_total_size', 'average_resident_set_size',
'signals_delivered', 'page_size', 'exit_status'
]
float_list = ['real_time', 'user_time', 'system_time'] float_list = ['real_time', 'user_time', 'system_time']
for key in proc_data: for key in proc_data:
if key in int_list: if key in int_list:

View File

@ -1,6 +1,7 @@
"""jc - JSON CLI output utility `timedatectl` command output parser """jc - JSON CLI output utility `timedatectl` command output parser
The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the `universal_time` field is available. The `epoch_utc` calculated timestamp field is timezone-aware and is only
available if the `universal_time` field is available.
Usage (cli): Usage (cli):
@ -25,7 +26,7 @@ Schema:
{ {
"local_time": string, "local_time": string,
"universal_time": string, "universal_time": string,
"epoch_utc": integer, # timezone-aware timestamp "epoch_utc": integer, # timezone-aware
"rtc_time": string, "rtc_time": string,
"time_zone": string, "time_zone": string,
"ntp_enabled": boolean, "ntp_enabled": boolean,
@ -72,9 +73,6 @@ class info():
description = '`timedatectl status` command parser' description = '`timedatectl status` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['timedatectl', 'timedatectl status'] magic_commands = ['timedatectl', 'timedatectl status']

View File

@ -141,8 +141,6 @@ class info():
description = '`tracepath` and `tracepath6` command parser' description = '`tracepath` and `tracepath6` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['tracepath', 'tracepath6'] magic_commands = ['tracepath', 'tracepath6']

View File

@ -2,7 +2,10 @@
Supports `traceroute` and `traceroute6` output. Supports `traceroute` and `traceroute6` output.
Note: On some operating systems you will need to redirect `STDERR` to `STDOUT` for destination info since the header line is sent to `STDERR`. A warning message will be printed to `STDERR` if the header row is not found. Note: On some operating systems you will need to redirect `STDERR` to
`STDOUT` for destination info since the header line is sent to
`STDERR`. A warning message will be printed to `STDERR` if the
header row is not found.
e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute` e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
@ -129,8 +132,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the trparse library by Luis Benitez at https://github.com/lbenitez000/trparse' details = 'Using the trparse library by Luis Benitez at https://github.com/lbenitez000/trparse'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['traceroute', 'traceroute6'] magic_commands = ['traceroute', 'traceroute6']

View File

@ -45,7 +45,7 @@ Schema:
"end": integer "end": integer
} }
], ],
"to_service": string, # null if any to ports or port_ranges are set "to_service": string, # [0]
"from_ip": string, "from_ip": string,
"from_ip_prefix": integer, "from_ip_prefix": integer,
"from_interface": string, "from_interface": string,
@ -59,12 +59,15 @@ Schema:
"end": integer "end": integer
} }
], ],
"from_service": string, # null if any from ports or port_ranges are set "from_service": string, # [1]
"comment": string # null if no comment "comment": string # null if no comment
} }
] ]
} }
[0] null if any 'to' ports or port_ranges are set
[1] null if any 'from' ports or port_ranges are set
Examples: Examples:
$ ufw status verbose | jc --ufw -p $ ufw status verbose | jc --ufw -p

View File

@ -1,8 +1,12 @@
"""jc - JSON CLI output utility `ufw app info [application]` command output parser """jc - JSON CLI output utility `ufw app info [application]` command
output parser
Supports individual apps via `ufw app info [application]` and all apps list via `ufw app info all`. Supports individual apps via `ufw app info [application]` and all apps list
via `ufw app info all`.
Because `ufw` application definitions allow overlapping ports and port ranges, this parser preserves that behavior, but also provides `normalized` lists and ranges that remove duplicate ports and merge overlapping ranges. Because `ufw` application definitions allow overlapping ports and port
ranges, this parser preserves that behavior, but also provides `normalized`
lists and ranges that remove duplicate ports and merge overlapping ranges.
Usage (cli): Usage (cli):
@ -43,31 +47,35 @@ Schema:
], ],
"udp_ranges": [ "udp_ranges": [
{ {
"start": integer, # 'any' is converted to start/end: 0/65535 "start": integer, # [0]
"end": integer "end": integer
} }
], ],
"normalized_tcp_list": [ "normalized_tcp_list": [
integers # duplicates and overlapping are removed integers # [1]
], ],
"normalized_tcp_ranges": [ "normalized_tcp_ranges": [
{ {
"start": integer, # 'any' is converted to start/end: 0/65535 "start": integer, # [0]
"end": integers # overlapping are merged "end": integers # [2]
} }
], ],
"normalized_udp_list": [ "normalized_udp_list": [
integers # duplicates and overlapping are removed integers # [1]
], ],
"normalized_udp_ranges": [ "normalized_udp_ranges": [
{ {
"start": integer, # 'any' is converted to start/end: 0/65535 "start": integer, # [0]
"end": integers # overlapping are merged "end": integers # [2]
} }
] ]
} }
] ]
[0] 'any' is converted to start/end: 0/65535
[1] duplicates and overlapping are removed
[2] overlapping are merged
Examples: Examples:
$ ufw app info MSN | jc --ufw-appinfo -p $ ufw app info MSN | jc --ufw-appinfo -p

View File

@ -57,8 +57,6 @@ class info():
description = '`uname -a` command parser' description = '`uname -a` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'freebsd'] compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['uname'] magic_commands = ['uname']

View File

@ -13,16 +13,18 @@ def simple_table_parse(data):
Parameters: Parameters:
data: (list) Text data to parse that has been split into lines via .splitlines(). data: (list) Text data to parse that has been split into lines
Item 0 must be the header row. Any spaces in header names should be via .splitlines(). Item 0 must be the header row.
changed to underscore '_'. You should also ensure headers are Any spaces in header names should be changed to
lowercase by using .lower(). underscore '_'. You should also ensure headers are
lowercase by using .lower().
Also, ensure there are no blank lines (list items) in the data. Also, ensure there are no blank lines (list items)
in the data.
Returns: Returns:
List of Dictionaries raw structured data List of Dictionaries
""" """
headers = [h for h in ' '.join(data[0].strip().split()).split() if h] headers = [h for h in ' '.join(data[0].strip().split()).split() if h]
raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), data[1:]) raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), data[1:])
@ -37,22 +39,26 @@ def sparse_table_parse(data, delim='\u2063'):
Parameters: Parameters:
data: (list) Text data to parse that has been split into lines via .splitlines(). data: (list) Text data to parse that has been split into lines
Item 0 must be the header row. Any spaces in header names should be via .splitlines(). Item 0 must be the header row.
changed to underscore '_'. You should also ensure headers are Any spaces in header names should be changed to
lowercase by using .lower(). Do not change the position of header underscore '_'. You should also ensure headers are
names as the positions are used to find the data. lowercase by using .lower(). Do not change the
position of header names as the positions are used
to find the data.
Also, ensure there are no blank lines (list items) in the data. Also, ensure there are no blank lines (list items)
in the data.
delim: (string) Delimiter to use. By default 'u\2063' (invisible separator) is used delim: (string) Delimiter to use. By default 'u\2063' (invisible
since this is unlikely to ever be seen in terminal output. You can separator) is used since this is unlikely to ever
change this for troubleshooting purposes or if there is a delimiter be seen in terminal output. You can change this for
conflict with your data. troubleshooting purposes or if there is a delimiter
conflict with your data.
Returns: Returns:
List of Dictionaries raw structured data List of Dictionaries
""" """
output = [] output = []
header_text = data.pop(0) header_text = data.pop(0)

View File

@ -1,8 +1,10 @@
"""jc - JSON CLI output utility `upower` command output parser """jc - JSON CLI output utility `upower` command output parser
The `updated_epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `updated_epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `updated_epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. The `updated_epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -31,8 +33,8 @@ Schema:
"native_path": string, "native_path": string,
"power_supply": boolean, "power_supply": boolean,
"updated": string, "updated": string,
"updated_epoch": integer, # null if date-time conversion fails "updated_epoch": integer, # [0]
"updated_epoch_utc": integer, # null if date-time conversion fails "updated_epoch_utc": integer, # [0]
"updated_seconds_ago": integer, "updated_seconds_ago": integer,
"has_history": boolean, "has_history": boolean,
"has_statistics": boolean, "has_statistics": boolean,
@ -84,12 +86,14 @@ Schema:
} }
] ]
[0] null if date-time conversion fails
Examples: Examples:
$ upower -i /org/freedesktop/UPower/devices/battery | jc --upower -p $ upower -i /org/freedesktop/UPower/devices/battery | jc --upower -p
[ [
{ {
"native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT0", "native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/p...",
"vendor": "NOTEBOOK", "vendor": "NOTEBOOK",
"model": "BAT", "model": "BAT",
"serial": "0001", "serial": "0001",
@ -148,7 +152,7 @@ Examples:
$ upower -i /org/freedesktop/UPower/devices/battery | jc --upower -p -r $ upower -i /org/freedesktop/UPower/devices/battery | jc --upower -p -r
[ [
{ {
"native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT0", "native_path": "/sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/p...",
"vendor": "NOTEBOOK", "vendor": "NOTEBOOK",
"model": "BAT", "model": "BAT",
"serial": "0001", "serial": "0001",
@ -203,9 +207,6 @@ class info():
description = '`upower` command parser' description = '`upower` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['upower'] magic_commands = ['upower']
@ -238,7 +239,10 @@ def _process(proc_data):
entry['updated_epoch_utc'] = ts.utc entry['updated_epoch_utc'] = ts.utc
# top level boolean conversions # top level boolean conversions
bool_list = ['power_supply', 'has_history', 'has_statistics', 'on_battery', 'lid_is_closed', 'lid_is_present'] bool_list = [
'power_supply', 'has_history', 'has_statistics', 'on_battery', 'lid_is_closed',
'lid_is_present'
]
for key in entry: for key in entry:
if key in bool_list: if key in bool_list:
entry[key] = jc.utils.convert_to_bool(entry[key]) entry[key] = jc.utils.convert_to_bool(entry[key])
@ -374,7 +378,9 @@ def parse(data, raw=False, quiet=False):
# general detail lines # general detail lines
if line.startswith(' ') and ':' in line: if line.startswith(' ') and ':' in line:
key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_').replace(' ', '_').replace('(', '').replace(')', '') key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_')\
.replace(' ', '_').replace('(', '')\
.replace(')', '')
val = line.split(':', maxsplit=1)[1].strip() val = line.split(':', maxsplit=1)[1].strip()
device_obj['detail'][key] = val device_obj['detail'][key] = val
continue continue
@ -393,7 +399,9 @@ def parse(data, raw=False, quiet=False):
# top level lines # top level lines
if line.startswith(' ') and ':' in line: if line.startswith(' ') and ':' in line:
key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_').replace(' ', '_').replace('(', '').replace(')', '') key = line.split(':', maxsplit=1)[0].strip().lower().replace('-', '_')\
.replace(' ', '_').replace('(', '')\
.replace(')', '')
val = line.split(':', maxsplit=1)[1].strip() val = line.split(':', maxsplit=1)[1].strip()
device_obj[key] = val device_obj[key] = val
continue continue

View File

@ -74,8 +74,6 @@ class info():
description = '`uptime` command parser' description = '`uptime` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['uptime'] magic_commands = ['uptime']

View File

@ -2,9 +2,11 @@
Options supported: `-a`, `-w`, `-d`, `-t` Options supported: `-a`, `-w`, `-d`, `-t`
The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `epoch` calculated timestamp field is naive. (i.e. based on the local
time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. The `epoch_utc` calculated timestamp field is timezone-aware and is only
available if the timezone field is UTC.
Usage (cli): Usage (cli):
@ -60,11 +62,14 @@ Schema:
"io_seconds": integer, "io_seconds": integer,
"timestamp": string, "timestamp": string,
"timezone": string, "timezone": string,
"epoch": integer, # naive timestamp if -t flag is used "epoch": integer, # [0]
"epoch_utc": integer # aware timestamp if -t flag is used and UTC TZ "epoch_utc": integer # [1]
} }
] ]
[0] naive timestamp if -t flag is used
[1] aware timestamp if -t flag is used and UTC TZ
Examples: Examples:
$ vmstat | jc --vmstat -p $ vmstat | jc --vmstat -p
@ -130,9 +135,6 @@ class info():
description = '`vmstat` command parser' description = '`vmstat` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
magic_commands = ['vmstat'] magic_commands = ['vmstat']
@ -153,11 +155,13 @@ def _process(proc_data):
List of Dictionaries. Structured to conform to the schema. List of Dictionaries. Structured to conform to the schema.
""" """
int_list = ['runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem', 'buffer_mem', int_list = [
'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in', 'blocks_out', 'runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem',
'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time', 'io_wait_time', 'buffer_mem', 'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in',
'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms', 'total_writes', 'blocks_out', 'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time',
'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds'] 'io_wait_time', 'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms',
'total_writes', 'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds'
]
for entry in proc_data: for entry in proc_data:
for key in entry: for key in entry:

View File

@ -4,83 +4,100 @@
Options supported: `-a`, `-w`, `-d`, `-t` Options supported: `-a`, `-w`, `-d`, `-t`
The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `epoch` calculated timestamp field is naive. (i.e. based on the local
time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is only available if the timezone field is UTC. The `epoch_utc` calculated timestamp field is timezone-aware and is only
available if the timezone field is UTC.
Usage (cli): Usage (cli):
$ vmstat | jc --vmstat-s $ vmstat | jc --vmstat-s
> Note: When piping `jc` converted `vmstat` output to other processes it may appear the output is hanging due to the OS pipe buffers. This is because `vmstat` output is too small to quickly fill up the buffer. Use the `-u` option to unbuffer the `jc` output if you would like immediate output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output) for more information. > Note: When piping `jc` converted `vmstat` output to other processes it may
appear the output is hanging due to the OS pipe buffers. This is because
`vmstat` output is too small to quickly fill up the buffer. Use the `-u`
option to unbuffer the `jc` output if you would like immediate output. See
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
for more information.
Usage (module): Usage (module):
import jc import jc
result = jc.parse('vmstat_s', vmstat_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parse('vmstat_s', vmstat_command_output.splitlines())
for item in result: for item in result:
# do something # do something
or or
import jc.parsers.vmstat_s import jc.parsers.vmstat_s
result = jc.parsers.vmstat_s.parse(vmstat_command_output.splitlines()) # result is an iterable object # result is an iterable object (generator)
result = jc.parsers.vmstat_s.parse(vmstat_command_output.splitlines())
for item in result: for item in result:
# do something # do something
Schema: Schema:
{ {
"runnable_procs": integer, "runnable_procs": integer,
"uninterruptible_sleeping_procs": integer, "uninterruptible_sleeping_procs": integer,
"virtual_mem_used": integer, "virtual_mem_used": integer,
"free_mem": integer, "free_mem": integer,
"buffer_mem": integer, "buffer_mem": integer,
"cache_mem": integer, "cache_mem": integer,
"inactive_mem": integer, "inactive_mem": integer,
"active_mem": integer, "active_mem": integer,
"swap_in": integer, "swap_in": integer,
"swap_out": integer, "swap_out": integer,
"blocks_in": integer, "blocks_in": integer,
"blocks_out": integer, "blocks_out": integer,
"interrupts": integer, "interrupts": integer,
"context_switches": integer, "context_switches": integer,
"user_time": integer, "user_time": integer,
"system_time": integer, "system_time": integer,
"idle_time": integer, "idle_time": integer,
"io_wait_time": integer, "io_wait_time": integer,
"stolen_time": integer, "stolen_time": integer,
"disk": string, "disk": string,
"total_reads": integer, "total_reads": integer,
"merged_reads": integer, "merged_reads": integer,
"sectors_read": integer, "sectors_read": integer,
"reading_ms": integer, "reading_ms": integer,
"total_writes": integer, "total_writes": integer,
"merged_writes": integer, "merged_writes": integer,
"sectors_written": integer, "sectors_written": integer,
"writing_ms": integer, "writing_ms": integer,
"current_io": integer, "current_io": integer,
"io_seconds": integer, "io_seconds": integer,
"timestamp": string, "timestamp": string,
"timezone": string, "timezone": string,
"epoch": integer, # naive timestamp if -t flag is used "epoch": integer, # [0]
"epoch_utc": integer # aware timestamp if -t flag is used and UTC TZ "epoch_utc": integer # [1]
"_jc_meta": # This object only exists if using -qq or ignore_exceptions=True
# Below object only exists if using -qq or ignore_exceptions=True
"_jc_meta":
{ {
"success": boolean, # true if successfully parsed, false if error "success": boolean, # [2]
"error": string, # exists if "success" is false "error": string, # [3]
"line": string # exists if "success" is false "line": string # [3]
} }
} }
[0] naive timestamp if -t flag is used
[1] aware timestamp if -t flag is used and UTC TZ
[2] false if error parsing
[3] exists if "success" is false
Examples: Examples:
$ vmstat | jc --vmstat-s $ vmstat | jc --vmstat-s
{"runnable_procs":2,"uninterruptible_sleeping_procs":0,"virtual_mem_used":0,"free_mem":2794468,"buffer_mem":2108,"cache_mem":741208,"inactive_mem":null,"active_mem":null,"swap_in":0,"swap_out":0,"blocks_in":1,"blocks_out":3,"interrupts":29,"context_switches":57,"user_time":0,"system_time":0,"idle_time":99,"io_wait_time":0,"stolen_time":0,"timestamp":null,"timezone":null} {"runnable_procs":2,"uninterruptible_sleeping_procs":0,"virtual_mem...}
... ...
$ vmstat | jc --vmstat-s -r $ vmstat | jc --vmstat-s -r
{"runnable_procs":"2","uninterruptible_sleeping_procs":"0","virtual_mem_used":"0","free_mem":"2794468","buffer_mem":"2108","cache_mem":"741208","inactive_mem":null,"active_mem":null,"swap_in":"0","swap_out":"0","blocks_in":"1","blocks_out":"3","interrupts":"29","context_switches":"57","user_time":"0","system_time":"0","idle_time":"99","io_wait_time":"0","stolen_time":"0","timestamp":null,"timezone":null} {"runnable_procs":"2","uninterruptible_sleeping_procs":"0","virtua...}
... ...
""" """
import jc.utils import jc.utils
@ -94,8 +111,6 @@ class info():
description = '`vmstat` command streaming parser' description = '`vmstat` command streaming parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux'] compatible = ['linux']
streaming = True streaming = True
@ -115,11 +130,13 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema. Dictionary. Structured data to conform to the schema.
""" """
int_list = ['runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem', 'buffer_mem', int_list = [
'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in', 'blocks_out', 'runnable_procs', 'uninterruptible_sleeping_procs', 'virtual_mem_used', 'free_mem',
'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time', 'io_wait_time', 'buffer_mem', 'cache_mem', 'inactive_mem', 'active_mem', 'swap_in', 'swap_out', 'blocks_in',
'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms', 'total_writes', 'blocks_out', 'interrupts', 'context_switches', 'user_time', 'system_time', 'idle_time',
'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds'] 'io_wait_time', 'stolen_time', 'total_reads', 'merged_reads', 'sectors_read', 'reading_ms',
'total_writes', 'merged_writes', 'sectors_written', 'writing_ms', 'current_io', 'io_seconds'
]
for key in proc_data: for key in proc_data:
if key in int_list: if key in int_list:
@ -139,7 +156,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
Parameters: Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines()) data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True ignore_exceptions: (boolean) ignore parsing exceptions if True

View File

@ -113,8 +113,6 @@ class info():
description = '`w` command parser' description = '`w` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['w'] magic_commands = ['w']

View File

@ -63,8 +63,6 @@ class info():
description = '`wc` command parser' description = '`wc` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['wc'] magic_commands = ['wc']

View File

@ -2,7 +2,8 @@
Accepts any of the following who options (or no options): `-aTH` Accepts any of the following who options (or no options): `-aTH`
The `epoch` calculated timestamp field is naive (i.e. based on the local time of the system the parser is run on) The `epoch` calculated timestamp field is naive. (i.e. based on the local
time of the system the parser is run on)
Usage (cli): Usage (cli):
@ -31,7 +32,7 @@ Schema:
"writeable_tty": string, "writeable_tty": string,
"tty": string, "tty": string,
"time": string, "time": string,
"epoch": integer, # naive timestamp. null if time cannot be converted "epoch": integer, # [0]
"idle": string, "idle": string,
"pid": integer, "pid": integer,
"from": string, "from": string,
@ -39,6 +40,8 @@ Schema:
} }
] ]
[0] naive timestamp. null if time cannot be converted
Examples: Examples:
$ who -a | jc --who -p $ who -a | jc --who -p
@ -142,9 +145,6 @@ class info():
description = '`who` command parser' description = '`who` command parser'
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['who'] magic_commands = ['who']

View File

@ -81,8 +81,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the xmltodict library at https://github.com/martinblech/xmltodict' details = 'Using the xmltodict library at https://github.com/martinblech/xmltodict'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']

View File

@ -95,8 +95,6 @@ class info():
author = 'Kelly Brazil' author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com' author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the ruamel.yaml library at https://pypi.org/project/ruamel.yaml' details = 'Using the ruamel.yaml library at https://pypi.org/project/ruamel.yaml'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']