1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2026-04-03 17:44:07 +02:00

Compare commits

...

341 Commits

Author SHA1 Message Date
Kelly Brazil
400f5a44ec Merge pull request #48 from kellyjonbrazil/dev
Dev v1.9.0
2020-03-11 13:37:22 -07:00
Kelly Brazil
a2ab5bab91 version bump to v1.9.0 2020-03-11 13:32:58 -07:00
Kelly Brazil
fc8ab27361 bugfix for misaligned columns and additional test for ntpq #31 2020-03-11 13:24:55 -07:00
Kelly Brazil
59f19d33a5 add file command tests for #41 2020-03-11 12:39:59 -07:00
Kelly Brazil
dfc9618115 add file parser for issue #41 2020-03-11 12:20:58 -07:00
Kelly Brazil
8e02e5c75a fix issue with getting options with some commands #47 2020-03-11 09:21:14 -07:00
Kelly Brazil
970493ab93 add magic commands 2020-03-11 06:22:54 -07:00
Kelly Brazil
64d78956eb update acknowledgment 2020-03-10 22:18:26 -07:00
Kelly Brazil
40c05346f4 re-adding optimizations from https://github.com/philippeitis 2020-03-10 22:16:40 -07:00
Kelly Brazil
e9b0bc1409 doc update 2020-03-10 22:03:54 -07:00
Kelly Brazil
798e6bb7d9 tests passing for airport -s. issue #46 2020-03-10 22:03:44 -07:00
Kelly Brazil
12a370deed add airport -s parser for issue #46 2020-03-10 21:51:02 -07:00
Kelly Brazil
553bfbe1a0 tests passing for airport -I. Issue #46 2020-03-10 21:02:17 -07:00
Kelly Brazil
52494321fc fixes and docs for airport parser issue #46 2020-03-10 20:55:07 -07:00
Kelly Brazil
c6c9e06496 added airport command parser 2020-03-10 20:35:52 -07:00
Kelly Brazil
e3a6c05a58 timedatectl fixes, tests, and fixtures for issue #42 2020-03-10 20:26:53 -07:00
Kelly Brazil
391d06f68d change selection_state to state 2020-03-10 20:16:41 -07:00
Kelly Brazil
99804ea06e added timedatectl status parser 2020-03-10 18:37:55 -07:00
Kelly Brazil
51935deb2a timedatectl test fixtures 2020-03-10 18:00:47 -07:00
Kelly Brazil
b24d0c3a47 ntpq docs 2020-03-10 18:00:26 -07:00
Kelly Brazil
762a886d6f add ntpq tests 2020-03-10 15:17:25 -07:00
Kelly Brazil
2c3e9ddfe4 add ntpq parser for issue #31 2020-03-10 14:18:55 -07:00
Kelly Brazil
c7cd2b63c8 delete unused test file 2020-03-09 11:46:17 -07:00
Kelly Brazil
f0528ea831 Merge pull request #45 from kellyjonbrazil/dev
Dev v1.8.1
2020-03-08 14:54:13 -07:00
Kelly Brazil
5bc5596f60 version bump to 1.8.1 2020-03-08 14:49:23 -07:00
Kelly Brazil
2c27ac46be add ls test fixtures 2020-03-08 14:43:51 -07:00
Kelly Brazil
caad840153 Merge pull request #44 from philippeitis/patch-5
Move core magic() logic into seperate function for testability, minor tweaks
2020-03-08 14:19:37 -07:00
philippeitis
65bd7e2904 Merge pull request #1 from kellyjonbrazil/pr/44
Merge changes
2020-03-08 14:10:35 -07:00
Kelly Brazil
c3d7d7db12 removed whitespace 2020-03-08 14:03:08 -07:00
Kelly Brazil
5605310362 added tests, removed os import, changed to 'assertEqual' 2020-03-08 14:02:54 -07:00
philippeitis
17b6efe82e Create basic tests for generate_magic_commands() 2020-03-08 13:35:01 -07:00
philippeitis
a032ae56ae Pass args to generate_magic_command() to allow testing. 2020-03-08 13:26:15 -07:00
philippeitis
eab2f4b056 Move core magic() logic into seperate function for testability, minor tweaks.
We only care about the command when testing magic() - by moving that out, we can easily test the command. I modified the code to return a boolean signalling that the command is valid, and the command itself to maintain the original functionality.

I also made some small tweaks (removed a list() call, fixed a possible bug with no arguments., moved magic_dict instantiation past the fast path checks to avoid making a dict if not needed.)
2020-03-08 13:20:38 -07:00
Kelly Brazil
aff86ae6c7 reimpliment magic() based on the dictionary approach suggested by philippeitis 2020-03-08 12:58:26 -07:00
Kelly Brazil
7ece9ddc1a version bump ls 2020-03-07 17:26:42 -08:00
Kelly Brazil
7cd048e839 changelog update 2020-03-07 17:25:10 -08:00
Kelly Brazil
1e22f610a3 fix for osx - doesn't print 'total xx' line if empty directory (issue #40) 2020-03-07 17:22:08 -08:00
Kelly Brazil
5249c972ae add to changelog 2020-03-06 12:09:20 -08:00
Kelly Brazil
fd45f856a0 import jc.utils instead of jc 2020-03-06 12:09:09 -08:00
Kelly Brazil
c8ab40cd33 ignore .github folder 2020-03-05 09:19:58 -08:00
Kelly Brazil
b2c872925b add utf-8 encoding for testing on Windows 2020-03-04 19:47:03 -08:00
Kelly Brazil
f48e229202 utf-8 open for windows tests 2020-03-04 19:40:32 -08:00
Kelly Brazil
799fec92c3 utf-8 for windows support 2020-03-04 19:33:45 -08:00
Kelly Brazil
87a41c2fca add utf-8 to open function 2020-03-04 19:30:30 -08:00
Kelly Brazil
7f85de0c46 add windows-latest 2020-03-04 19:28:21 -08:00
Kelly Brazil
13661b1993 Merge pull request #37 from philippeitis/continuous_integration
Enable Continuous Integration with GitHub Actions.
2020-03-04 16:54:26 -08:00
philippeitis
51d5c3892d Remove Windows tests, due to lack of support. 2020-03-04 16:21:06 -08:00
philippeitis
e4eab4641a Change line in blkid.py to trigger CI 2020-03-04 16:17:58 -08:00
philippeitis
9b148e0ba3 Add requirements.txt 2020-03-04 16:16:19 -08:00
philippeitis
de28932650 Consolidate dictionary into creation, trigger CI 2020-03-04 16:14:03 -08:00
Kelly Brazil
5f798d603e version bump and ack to philippeitis 2020-03-04 16:11:14 -08:00
Kelly Brazil
a0757b2dd3 optimize line parsing 2020-03-04 16:07:53 -08:00
philippeitis
498d51b4e8 Enable Continuous Integration with GitHub Actions.
This automatically runs unit tests on various operating systems and Python versions when Python files are modified to ensure that functionality remains correct.
2020-03-04 16:07:32 -08:00
Kelly Brazil
b06b6bae3f Merge pull request #36 from philippeitis/patch-3
Simplify process() in history.py, avoid list allocation in parse()
2020-03-04 16:04:05 -08:00
Kelly Brazil
b5eaff2137 Merge pull request #35 from kellyjonbrazil/revert-34-patch-3
Revert "Simplify process() in history.py, avoid list allocation in parse()"
2020-03-04 15:33:13 -08:00
Kelly Brazil
c01bcd3734 Revert "Simplify process() in history.py, avoid list allocation in parse()" 2020-03-04 15:32:23 -08:00
Kelly Brazil
d75c4068ca Merge pull request #34 from philippeitis/patch-3
Simplify process() in history.py, avoid list allocation in parse()
2020-03-04 15:31:55 -08:00
Kelly Brazil
6aa2d5a3d2 Merge pull request #33 from philippeitis/patch-2
Handle case where only options are passed.
2020-03-04 15:28:09 -08:00
philippeitis
065276805f Simplify process() in history.py, avoid list allocation in parse() 2020-03-04 13:35:31 -08:00
philippeitis
a63408c8cf Handle case where only options are passed. 2020-03-04 13:16:35 -08:00
Kelly Brazil
69576f6bfa minor sytax fixes 2020-03-04 12:03:40 -08:00
Kelly Brazil
19845624e2 Merge pull request #32 from philippeitis/patch-1
Simplify main(), magic() methods.
2020-03-04 11:59:29 -08:00
philippeitis
22ff2964e9 Simplify main(), magic() methods. 2020-03-04 10:33:42 -08:00
Kelly Brazil
d96b3a65a9 formatting 2020-03-04 08:30:52 -08:00
Kelly Brazil
4989445ef4 Merge pull request #30 from kellyjonbrazil/dev
Dev v1.8.0
2020-03-03 11:46:09 -08:00
Kelly Brazil
6770892acd add release notes link 2020-03-03 11:37:59 -08:00
Kelly Brazil
d4eba8740f release date 3/3 2020-03-03 11:08:52 -08:00
Kelly Brazil
9f60760560 add group and gshadow tests 2020-03-03 10:54:27 -08:00
Kelly Brazil
0a8f8ac934 add group and gshadow parsers 2020-03-03 09:55:43 -08:00
Kelly Brazil
6ae24c8244 add group and gshadow test fixtures 2020-03-03 09:55:17 -08:00
Kelly Brazil
d3679082a8 add group and gshadow parsers 2020-03-03 09:36:16 -08:00
Kelly Brazil
fb08b42dca change 'group_list' to 'members' 2020-03-03 09:32:56 -08:00
Kelly Brazil
4aeaa9f42a add /etc/gshadow parser 2020-03-03 09:32:25 -08:00
Kelly Brazil
5f5693da04 spelling fix 2020-03-03 09:07:28 -08:00
Kelly Brazil
5eb0f61727 add /etc/group file parser 2020-03-03 09:07:09 -08:00
Kelly Brazil
958e998991 formatting 2020-03-02 17:15:05 -08:00
Kelly Brazil
b78c1509f6 try/except dialect detection 2020-03-02 15:06:25 -08:00
Kelly Brazil
ce184d4d57 add csv parser tests 2020-03-02 15:05:56 -08:00
Kelly Brazil
b4c3714ced removed [OPTIONS] PARSER syntax. still works but prefer the PARSER [OPTIONS] syntax for better performance 2020-03-02 14:10:15 -08:00
Kelly Brazil
5b7dfa0438 formatting 2020-03-02 14:07:56 -08:00
Kelly Brazil
391a388476 doc update 2020-03-02 14:07:29 -08:00
Kelly Brazil
d9c4e2ed4c add csv file parser 2020-03-02 14:03:58 -08:00
Kelly Brazil
0c42db38b1 doc update 2020-03-02 10:30:12 -08:00
Kelly Brazil
2f9be8bf33 simplify usage 2020-03-02 08:32:42 -08:00
Kelly Brazil
e8c00155e8 add -b to warning message 2020-03-02 07:43:45 -08:00
Kelly Brazil
cc88fdd9ee update example 2020-03-01 21:17:50 -08:00
Kelly Brazil
d9de11ef1d add another who example 2020-03-01 21:16:57 -08:00
Kelly Brazil
0ceda97d09 who parser tests 2020-03-01 19:03:27 -08:00
Kelly Brazil
d0dec92ba8 add who test fixtures 2020-03-01 18:57:51 -08:00
Kelly Brazil
d420c008d8 fix for pts lines with no user info 2020-03-01 17:52:14 -08:00
Kelly Brazil
f0b32db433 who doc update 2020-03-01 17:39:02 -08:00
Kelly Brazil
bc838eda59 fix output for non-extended 2020-03-01 17:38:51 -08:00
Kelly Brazil
afe55b6af0 add who parser 2020-03-01 17:07:28 -08:00
Kelly Brazil
dd3a3ac302 doc update and process pid integers 2020-03-01 17:04:06 -08:00
Kelly Brazil
f9982a7947 fixes for from and comment fields 2020-03-01 16:49:52 -08:00
Kelly Brazil
07c1be9e9a add who command parser 2020-03-01 16:30:04 -08:00
Kelly Brazil
f832b88755 add passwd and shadow tests 2020-03-01 10:17:47 -08:00
Kelly Brazil
0fac757efc add passwd and shadow parsers 2020-02-29 12:25:41 -08:00
Kelly Brazil
fc15742065 passwd and shadow test fixtures 2020-02-29 12:25:22 -08:00
Kelly Brazil
6f2466a131 update readme with /etc/passwd and /etc/shadow file parsers 2020-02-29 11:56:12 -08:00
Kelly Brazil
4b90e22f0a doc update 2020-02-29 11:50:46 -08:00
Kelly Brazil
c493568785 doc fix 2020-02-29 11:46:38 -08:00
Kelly Brazil
1cdf004b77 add /etc/shadow parser 2020-02-29 11:46:24 -08:00
Kelly Brazil
a4ea504261 add /etc/passwd parser 2020-02-29 11:33:14 -08:00
Kelly Brazil
4c2c234c3b add last and lastb tests 2020-02-28 15:15:24 -08:00
Kelly Brazil
3d4c0f3e89 add blkid tests 2020-02-28 14:50:29 -08:00
Kelly Brazil
52fad02903 doc update 2020-02-28 13:31:38 -08:00
Kelly Brazil
9dcabc057c support multi device udev output 2020-02-28 10:57:14 -08:00
Kelly Brazil
db8c1079dd use maxsplit=1 in case there are multiple '=' delimiters 2020-02-28 09:54:07 -08:00
Kelly Brazil
8f954673ab use shlex split for values within quotations that have spaces 2020-02-28 09:07:36 -08:00
Kelly Brazil
79522d1c7d doc fixes 2020-02-28 08:51:48 -08:00
Kelly Brazil
a18bf03079 use raw strings for regular expressions 2020-02-28 08:50:35 -08:00
Kelly Brazil
c02b6b5d82 doc updates 2020-02-27 21:21:19 -08:00
Kelly Brazil
f99b423284 doc update 2020-02-27 21:04:24 -08:00
Kelly Brazil
d7d9d45d4f add missing comma 2020-02-27 20:59:09 -08:00
Kelly Brazil
90065ec0cd add more integers 2020-02-27 20:57:22 -08:00
Kelly Brazil
51157ebb86 another devname fix 2020-02-27 20:49:14 -08:00
Kelly Brazil
96d95c79ca devname fix 2020-02-27 20:47:07 -08:00
Kelly Brazil
e5da34c233 check if devname key exists before renaming 2020-02-27 20:41:06 -08:00
Kelly Brazil
f09d657f77 rename devname to device 2020-02-27 20:36:19 -08:00
Kelly Brazil
0f4b0189f5 process integer values 2020-02-27 20:31:17 -08:00
Kelly Brazil
4666042abb add blkid parser 2020-02-27 20:21:02 -08:00
Kelly Brazil
027d544c2b add last and lastb parser 2020-02-27 16:08:56 -08:00
Kelly Brazil
f1967d0138 system_boot fix 2020-02-27 16:08:39 -08:00
Kelly Brazil
c1d896027d fix system_boot tty 2020-02-27 15:58:12 -08:00
Kelly Brazil
5c2d2a6618 process function and docs 2020-02-27 15:44:36 -08:00
Kelly Brazil
997b269b0b btmp fix 2020-02-27 15:26:09 -08:00
Kelly Brazil
61257e7525 add last and lastb parser 2020-02-27 15:14:43 -08:00
Kelly Brazil
53ee2c3631 Merge pull request #29 from kellyjonbrazil/dev
Dev v1.7.5
2020-02-27 10:59:14 -08:00
Kelly Brazil
8bfa0bddec version bump to 1.7.5 2020-02-27 10:50:05 -08:00
Kelly Brazil
ad61e6bc81 add ls tests for filenames with newline characters 2020-02-27 10:48:09 -08:00
Kelly Brazil
873b5ba8ac move examples to bottom 2020-02-27 09:36:57 -08:00
Kelly Brazil
6ae50054e2 readme update 2020-02-24 20:30:44 -08:00
Kelly Brazil
22a35f41bf move variables to top 2020-02-24 17:50:56 -08:00
Kelly Brazil
961696c963 add a warning if newlines are detected in naked ls 2020-02-24 17:47:31 -08:00
Kelly Brazil
c7b7f1a5dc fix for files with newlines in naked ls 2020-02-24 17:24:56 -08:00
Kelly Brazil
b5a0d650b1 ls output with newlines 2020-02-24 17:01:33 -08:00
Kelly Brazil
573b279464 fixup for filenames that start with a newline character 2020-02-24 17:01:12 -08:00
Kelly Brazil
116e07f161 fixes for multiple consecutive newlines and trailing newlines in filenames 2020-02-24 16:38:29 -08:00
Kelly Brazil
964868c8af add support for newlines in filenames (only with ls -l) 2020-02-24 15:19:43 -08:00
Kelly Brazil
c8dac32df8 readme update 2020-02-24 13:05:35 -08:00
Kelly Brazil
72a0016bd8 use link to anchor for Parsers 2020-02-20 15:38:45 -08:00
Kelly Brazil
2ad3167434 update doc url 2020-02-19 07:12:43 -08:00
Kelly Brazil
ddabfaa05c Merge pull request #25 from kellyjonbrazil/dev
Dev v1.7.4
2020-02-19 07:05:29 -08:00
Kelly Brazil
f857523ca7 bump to version 1.7.4 2020-02-19 07:02:50 -08:00
Kelly Brazil
00d53858e8 add note about aliases not being supported 2020-02-17 22:57:15 -08:00
Kelly Brazil
c008167e66 add time-style=full-iso option to doc 2020-02-17 22:48:44 -08:00
Kelly Brazil
102344a041 formatting 2020-02-17 22:32:07 -08:00
Kelly Brazil
c865298ef3 remove unnecessary enumerate in for loop 2020-02-17 22:29:39 -08:00
Kelly Brazil
6ac03faf93 Revert "add ubuntu and centos default ls aliases to magic_commands"
This reverts commit 49c2701743.
2020-02-17 18:58:07 -08:00
Kelly Brazil
49c2701743 add ubuntu and centos default ls aliases to magic_commands 2020-02-17 18:55:03 -08:00
Kelly Brazil
d1a271b08e add new ls tests for recursive and multiple directories with glob 2020-02-17 18:33:55 -08:00
Kelly Brazil
7388ad19b9 bump to v1.8.0 2020-02-17 17:31:15 -08:00
Kelly Brazil
2e63cb5fad version bump ls to 1.1 2020-02-17 17:16:34 -08:00
Kelly Brazil
e7f14d02b1 update ls to allow multi directory (glob and -R). Adds 'parent' key if found 2020-02-17 17:14:27 -08:00
Kelly Brazil
873771d05a formatting 2020-02-17 09:16:32 -08:00
Kelly Brazil
d7de122e36 prettify link 2020-02-14 09:44:24 -08:00
Kelly Brazil
4ef0434f53 formatting update 2020-02-14 09:43:02 -08:00
Kelly Brazil
1aa2c99259 removed history from magic syntax 2020-02-13 22:10:22 -08:00
Kelly Brazil
c2450b27b0 Merge pull request #22 from kellyjonbrazil/dev
Dev 1.7.3
2020-02-13 21:26:18 -05:00
Kelly Brazil
14d6d8b84f version bump to 1.7.3 2020-02-13 18:24:53 -08:00
Kelly Brazil
f0e3846c03 formatting 2020-02-13 18:20:22 -08:00
Kelly Brazil
6ba64f1128 usage update 2020-02-13 18:19:19 -08:00
Kelly Brazil
13bcdbc6c9 doc update 2020-02-13 17:50:51 -08:00
Kelly Brazil
cfba62db20 correct parser search in magic() 2020-02-13 17:48:21 -08:00
Kelly Brazil
18fb69e36e docs/parsers link 2020-02-13 17:29:45 -08:00
Kelly Brazil
474eb0f3fd doc updates 2020-02-13 17:24:10 -08:00
Kelly Brazil
7f47b53370 add alternate magic syntax 2020-02-13 17:20:00 -08:00
Kelly Brazil
dc2907d3ce doc update 2020-02-13 16:58:25 -08:00
Kelly Brazil
1af85811e0 remove magic_command info 2020-02-13 16:57:57 -08:00
Kelly Brazil
1c1b19a478 doc update 2020-02-13 16:57:30 -08:00
Kelly Brazil
66942d64ba changelog update 2020-02-13 16:56:48 -08:00
Kelly Brazil
2fb6ae08d7 fix shlex usage 2020-02-13 12:17:41 -08:00
Kelly Brazil
bf8811e03e add comments 2020-02-13 10:25:41 -05:00
Kelly Brazil
c8b502c571 remove unnecessary join and add comments 2020-02-13 10:14:32 -05:00
Kelly Brazil
81c11a975c added docstrings 2020-02-13 10:08:43 -05:00
Kelly Brazil
0d370eb403 doc update 2020-02-13 10:03:11 -05:00
Kelly Brazil
7492c3f1e3 changelog update 2020-02-13 09:48:42 -05:00
Kelly Brazil
515a8a84b7 add "command" to description 2020-02-13 09:47:40 -05:00
Kelly Brazil
dd6680efb2 allow condensed options (-prdq is equivalent to -p -r -d -q) 2020-02-13 09:47:16 -05:00
Kelly Brazil
a7158373cd comment update 2020-02-12 00:16:17 -05:00
Kelly Brazil
6d50ec7199 add try/except to fix bare jc command condition 2020-02-12 00:11:48 -05:00
Kelly Brazil
95dbf98e8e allow options in magic syntax 2020-02-11 19:14:51 -08:00
Kelly Brazil
d49323e4eb add magic_commands list to info 2020-02-11 18:09:21 -08:00
Kelly Brazil
08c1e2aec9 add magic syntax 2020-02-11 18:08:59 -08:00
Kelly Brazil
a2c137df2e better magic command syntax logic using introspection information from parser modules 2020-02-11 18:08:37 -08:00
Kelly Brazil
fe27dcdb8f proof of concept for magic syntax (e.g. jc ls -al) 2020-02-11 12:16:23 -08:00
Kelly Brazil
028e136161 bump to 1.7.2: add test fixtures to package 2020-02-08 12:46:42 -08:00
Kelly Brazil
9a85a0a4d5 fix doc 2020-02-08 12:46:14 -08:00
Kelly Brazil
3a1cbc4d50 move info class to top 2020-02-05 22:26:47 -08:00
Kelly Brazil
77d334f7f3 Merge pull request #19 from kellyjonbrazil/dev-1.7.1
Dev v1.7.1
2020-02-05 16:59:52 -08:00
Kelly Brazil
53cdf863ac changelog update 2020-02-05 16:53:17 -08:00
Kelly Brazil
7b7e7fe0fe changelog update 2020-02-05 16:50:55 -08:00
Kelly Brazil
0c03132847 fix error codes using sys.exit() 2020-02-05 16:18:58 -08:00
Kelly Brazil
3b81f7e2a1 exit code on ctrl-c exit 2020-02-05 16:12:09 -08:00
Kelly Brazil
3d76437b43 doc fix 2020-02-05 16:00:23 -08:00
Kelly Brazil
4bc54c78ce fix compatibility list 2020-02-05 16:00:10 -08:00
Kelly Brazil
3d303a96b9 crontab bug fix and tests 2020-02-05 15:52:39 -08:00
Kelly Brazil
33c99d031d fix line clobbering bug 2020-02-05 15:12:59 -08:00
Kelly Brazil
caf7e9f69a fix line clobbering bug and add user field to shortcuts 2020-02-05 15:11:51 -08:00
Kelly Brazil
9449f1f5d5 crontab bugfix: inserting header row was clobbering the first data row 2020-02-05 14:44:49 -08:00
Kelly Brazil
6bad164b5e simplify by removing unnecessary getattr calls 2020-02-05 14:10:22 -08:00
Kelly Brazil
bb5ba7ddb1 add indent variable to helptext 2020-02-05 13:57:34 -08:00
Kelly Brazil
8b2e01d540 doc update 2020-02-05 13:50:12 -08:00
Kelly Brazil
ff1159b1de exit codes on error 2020-02-05 11:45:17 -08:00
Kelly Brazil
a2fd3202a0 description formatting change 2020-02-05 11:34:33 -08:00
Kelly Brazil
7b53715b91 change description 2020-02-05 11:08:58 -08:00
Kelly Brazil
e05fc0a510 change padding of helptext 2020-02-05 11:08:47 -08:00
Kelly Brazil
43604c33f6 doc update 2020-02-05 10:59:51 -08:00
Kelly Brazil
eb67c484ff add crontab-u to parsers list 2020-02-05 10:58:26 -08:00
Kelly Brazil
a7b7bdd467 load parser modules 'just in time' so we don't need to load all modules at startup 2020-02-05 10:55:08 -08:00
Kelly Brazil
ab06989a18 description updates 2020-02-04 21:46:52 -08:00
Kelly Brazil
657b722f94 ini to INI 2020-02-04 21:44:10 -08:00
Kelly Brazil
dd2aecad27 description update 2020-02-04 21:37:07 -08:00
Kelly Brazil
c82c5c5c64 changelog update 2020-02-04 21:34:57 -08:00
Kelly Brazil
a1761cd68f id tests 2020-02-04 21:25:33 -08:00
Kelly Brazil
d618a7f583 doc update 2020-02-04 21:17:03 -08:00
Kelly Brazil
831a42f660 id formatting 2020-02-04 21:12:32 -08:00
Kelly Brazil
3b36022e5a add id parser 2020-02-04 21:09:42 -08:00
Kelly Brazil
d01dfa25f1 changelog updates 2020-02-04 15:22:36 -08:00
Kelly Brazil
395a99037b crontab-u and history doc updates 2020-02-04 14:36:03 -08:00
Kelly Brazil
025986c51d change history 'line' to integer 2020-02-04 14:31:28 -08:00
Kelly Brazil
c56b83093f doc update 2020-02-04 14:19:33 -08:00
Kelly Brazil
7c712a4133 doc update 2020-02-04 14:18:14 -08:00
Kelly Brazil
9a0cfe6dfa minor formatting 2020-02-04 14:18:01 -08:00
Kelly Brazil
a116cdbcec tests for crontab-u 2020-02-04 14:11:34 -08:00
Kelly Brazil
f2d616c98e add crontab with user parser 2020-02-04 14:02:27 -08:00
Kelly Brazil
42cbd1777d add xml and yaml tests 2020-02-04 13:53:45 -08:00
Kelly Brazil
ebf375aac0 add ini tests 2020-02-04 12:18:31 -08:00
Kelly Brazil
1f9050267e add ini, xml, and yaml test files 2020-02-04 12:02:18 -08:00
Kelly Brazil
d7f9707a15 minor formatting 2020-02-04 11:18:32 -08:00
Kelly Brazil
ab589ee3ed add __version__ variable 2020-02-04 11:18:15 -08:00
Kelly Brazil
c84ec0361f xml example update 2020-02-03 22:25:30 -08:00
Kelly Brazil
47d2f8968a doc update 2020-02-03 22:21:40 -08:00
Kelly Brazil
019c480bcc update acknowledgments 2020-02-03 22:17:13 -08:00
Kelly Brazil
547c6d3d59 add xml parser 2020-02-03 22:13:06 -08:00
Kelly Brazil
b5ebf8b76a add ruamel.yaml ack 2020-02-03 21:41:53 -08:00
Kelly Brazil
c690e328f2 add examples 2020-02-03 21:38:21 -08:00
Kelly Brazil
cbb92c1a95 add ini and yaml 2020-02-03 21:38:08 -08:00
Kelly Brazil
beb41997c9 doc update 2020-02-03 21:28:11 -08:00
Kelly Brazil
755a6faf11 clean up multi-document support 2020-02-03 21:22:30 -08:00
Kelly Brazil
021f8350a3 update doc 2020-02-03 19:11:36 -08:00
Kelly Brazil
76583dcd2f add ini file parser 2020-02-03 19:07:31 -08:00
Kelly Brazil
bf033239a7 doc update 2020-02-03 16:20:38 -08:00
Kelly Brazil
eb37fccd37 doc update 2020-02-03 16:17:29 -08:00
Kelly Brazil
d04ad45331 setup for 1.7.1 2020-02-03 16:12:45 -08:00
Kelly Brazil
db157b8ca7 add yaml file parser 2020-02-03 16:12:32 -08:00
Kelly Brazil
68f277bb20 add __version__ 2020-02-03 16:11:58 -08:00
Kelly Brazil
4de8f42664 Merge pull request #17 from kellyjonbrazil/dev
Dev v1.6.1
2019-12-17 12:11:13 -08:00
Kelly Brazil
4f11855935 update version info 2019-12-17 12:09:24 -08:00
Kelly Brazil
2b9a5fcc32 update version 2019-12-17 12:05:40 -08:00
Kelly Brazil
224948d1f2 pip list and pip show tests 2019-12-17 11:44:43 -08:00
Kelly Brazil
36f2812d5a add support for legacy output 2019-12-17 10:58:00 -08:00
Kelly Brazil
be06aa2b31 update parse() Return info 2019-12-17 10:09:19 -08:00
Kelly Brazil
41f8e3aba2 update Return info 2019-12-17 09:56:09 -08:00
Kelly Brazil
093c0df897 schema info 2019-12-17 09:38:50 -08:00
Kelly Brazil
37afc7dc8a updte todo and compatibility 2019-12-17 09:35:27 -08:00
Kelly Brazil
efbf354960 doc update for pip show 2019-12-17 09:24:08 -08:00
Kelly Brazil
5e39fe0d80 pip show parser working 2019-12-17 09:20:26 -08:00
Kelly Brazil
47328dc659 add pip-show parser 2019-12-16 19:09:14 -08:00
Kelly Brazil
addeef50ba initial pip show parser add 2019-12-16 19:07:51 -08:00
Kelly Brazil
ad338cc5b5 schema doc update 2019-12-16 18:58:33 -08:00
Kelly Brazil
202bc8201e doc update 2019-12-16 18:54:19 -08:00
Kelly Brazil
5ff99de405 add argument to parser info 2019-12-16 18:40:08 -08:00
Kelly Brazil
86ebe2cf9c initial add of pip list parser 2019-12-16 18:36:13 -08:00
Kelly Brazil
facf0b399c add osx to campatible 2019-12-16 18:09:29 -08:00
Kelly Brazil
33db7b0bcb add crontab tests 2019-12-16 18:09:00 -08:00
Kelly Brazil
663d07bca1 add crontab 2019-12-16 17:52:09 -08:00
Kelly Brazil
ba04e4997f update docs 2019-12-16 17:51:11 -08:00
Kelly Brazil
c4fee1b658 add crontab parser 2019-12-16 17:50:52 -08:00
Kelly Brazil
99b92a15bb support shortcut schedules 2019-12-16 17:45:34 -08:00
Kelly Brazil
b076ab5b57 initial crontab parser 2019-12-16 17:01:53 -08:00
Kelly Brazil
687759f75d alphabetize du entry 2019-12-16 14:31:21 -08:00
Kelly Brazil
9eaac7f3af add du 2019-12-16 14:30:06 -08:00
Kelly Brazil
4c24e00cfc add osx-11 and ubuntu tests 2019-12-16 14:27:55 -08:00
Kelly Brazil
beb17011b0 du tests and docs 2019-12-16 13:57:42 -08:00
Kelly Brazil
e882bf55bc initial add du parser 2019-12-16 13:52:42 -08:00
Kelly Brazil
3a3016adb6 add parser_count to about 2019-12-16 11:52:18 -08:00
Kelly Brazil
1e8b68153a add osx uname tests 2019-12-16 11:12:45 -08:00
Kelly Brazil
9335cf65fb add uname osx support 2019-12-16 11:02:02 -08:00
Kelly Brazil
83f35256ae add OSX support 2019-12-16 11:01:43 -08:00
Kelly Brazil
4283333948 version bump 2019-12-16 10:03:47 -08:00
Kelly Brazil
b8f902796b shorten changelog 2019-12-16 10:03:34 -08:00
Kelly Brazil
8f99ab295c info update 2019-12-16 09:08:47 -08:00
Kelly Brazil
882310e268 add name to about parser info 2019-12-16 09:04:52 -08:00
Kelly Brazil
56bce95214 about code cleanup 2019-12-16 09:00:16 -08:00
Kelly Brazil
c13ecbec29 clean up parser info 2019-12-16 08:59:41 -08:00
Kelly Brazil
0ffaaa6e73 clean up about code 2019-12-16 08:18:37 -08:00
Kelly Brazil
75eff3adea remove whitespace 2019-12-14 23:56:40 -08:00
Kelly Brazil
bf5f80476c use real parser name in error message 2019-12-14 23:56:22 -08:00
Kelly Brazil
9aaf0fbb2f doc updates 2019-12-14 23:35:42 -08:00
Kelly Brazil
8f01ef7953 add -a option info 2019-12-14 23:27:56 -08:00
Kelly Brazil
da1d087452 add parser version info 2019-12-14 23:21:47 -08:00
Kelly Brazil
e16bc7e882 add about information to parsers 2019-12-14 23:15:15 -08:00
Kelly Brazil
fe9bdd4811 add info class 2019-12-13 20:01:51 -08:00
Kelly Brazil
17b6f3f6d6 add osx tests 2019-12-13 14:36:21 -08:00
Kelly Brazil
90a6baf0ee add osx tests 2019-12-13 14:30:12 -08:00
Kelly Brazil
f0e73d0e72 add osx tests 2019-12-13 10:50:01 -08:00
Kelly Brazil
a762882f1c fixture updates 2019-12-13 08:58:23 -08:00
Kelly Brazil
4c1bc59236 doc updates 2019-12-12 17:05:40 -08:00
Kelly Brazil
f2962083f8 add osx support for mount parser 2019-12-12 17:04:40 -08:00
Kelly Brazil
a0b22a5bcf help text formatting 2019-12-12 16:14:46 -08:00
Kelly Brazil
dcf393354c doc fix 2019-12-12 16:10:30 -08:00
Kelly Brazil
5f771656e3 use universal parser 2019-12-12 16:07:52 -08:00
Kelly Brazil
f376aab793 doc update 2019-12-12 15:59:36 -08:00
Kelly Brazil
3c96464217 osx fixes and tests 2019-12-12 15:59:24 -08:00
Kelly Brazil
c9892833a1 formatting change 2019-12-12 15:58:40 -08:00
Kelly Brazil
127c98affc changelog update 2019-12-12 15:58:24 -08:00
Kelly Brazil
8687a772f5 use universal parser 2019-12-12 15:33:34 -08:00
Kelly Brazil
b1162b14d4 use universal parser 2019-12-12 15:22:21 -08:00
Kelly Brazil
8a8ee35707 use universal parser 2019-12-12 15:01:42 -08:00
Kelly Brazil
5e109a3665 add du 2019-12-12 14:12:36 -08:00
Kelly Brazil
11db478430 update changelog 2019-12-12 14:12:21 -08:00
Kelly Brazil
a85377014d use universal parser 2019-12-12 14:11:59 -08:00
Kelly Brazil
3aea86234d fix osx-10.11.6 tests 2019-12-12 11:23:49 -08:00
Kelly Brazil
916ec6ed6b fix osx ls tests 2019-12-12 10:11:24 -08:00
Kelly Brazil
9dca6ba539 doc formatting change 2019-12-12 09:47:14 -08:00
Kelly Brazil
0ebb89f561 doc update 2019-12-12 09:41:56 -08:00
Kelly Brazil
e237867e24 doc formatting 2019-12-12 09:41:25 -08:00
Kelly Brazil
78fa44fd9a add compatibility to docs 2019-12-12 09:35:42 -08:00
Kelly Brazil
d615fa3b93 add compatibility to docs 2019-12-12 09:21:20 -08:00
Kelly Brazil
ce134dc332 Add OSX tests for ls 2019-12-12 09:09:57 -08:00
Kelly Brazil
a56e4dc752 use universal simple table parser 2019-12-11 17:27:48 -08:00
Kelly Brazil
d221b4aa29 changelog update 2019-12-11 17:19:38 -08:00
Kelly Brazil
d2cba6ad2f add compatibility info 2019-12-11 17:18:21 -08:00
Kelly Brazil
84b3c30b52 add osx tests 2019-12-11 17:18:04 -08:00
Kelly Brazil
68eeec19a8 doc update 2019-12-11 16:39:30 -08:00
Kelly Brazil
c6d1528a2e use _ instead of - 2019-12-11 16:37:13 -08:00
Kelly Brazil
50a6b256b8 new universal parsers to limit code duplication 2019-12-09 14:01:47 -08:00
Kelly Brazil
bbba1fe477 update df to use universal sparse table parser for osx compatibility 2019-12-09 14:01:29 -08:00
Kelly Brazil
46b827da6b add osx compatibility 2019-12-06 13:22:51 -08:00
Kelly Brazil
5e8c28a30a comment fix 2019-12-06 11:47:42 -08:00
Kelly Brazil
e5d3903164 update ifconfig doc 2019-12-06 11:46:09 -08:00
Kelly Brazil
23975c9c9e fixup osx subnet mask and convert state to an array 2019-12-06 11:44:57 -08:00
Kelly Brazil
1e0dab8355 ifconfig fixture updates 2019-12-06 10:53:49 -08:00
Kelly Brazil
5f4c10ffd5 doc update 2019-12-06 10:39:11 -08:00
Kelly Brazil
6f3d2b4b56 require ifconfig-parser v0.0.5 for mac and bytes support 2019-12-06 10:30:01 -08:00
Kelly Brazil
fea8ace844 add OSX compatibility 2019-12-06 10:27:11 -08:00
Kelly Brazil
6633d9262c Set theme jekyll-theme-cayman 2019-11-30 13:52:24 -08:00
Kelly Brazil
7d54137140 link update 2019-11-28 11:51:54 -08:00
Kelly Brazil
2fcda6f248 add motivation to readme 2019-11-25 18:34:21 -08:00
440 changed files with 108526 additions and 988 deletions

31
.github/workflows/pythonapp.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Test code
on:
push:
paths:
- "**/*.py"
pull_request:
paths:
- "**/*.py"
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
python-version: [3.6, 3.7, 3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test with unittest
run: |
python -m unittest discover tests

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ dist/
build/
*.egg-info/
jc/parsers.old/
.github/

1
MANIFEST.in Normal file
View File

@@ -0,0 +1 @@
graft tests/fixtures

1115
README.md

File diff suppressed because it is too large Load Diff

1
_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-cayman

View File

@@ -1,5 +1,66 @@
jc changelog
20200311 v1.9.0
- Added ntpq command parser
- Added timedatectl status command parser
- Added airport -I and airport -s command parser
- Added file command parser
- Optimized history command parser by https://github.com/philippeitis
- Magic syntax fix for certain edge cases
20200308 v1.8.1
- CLI optimizations by https://github.com/philippeitis
- Refactored magic syntax function and added tests (https://github.com/philippeitis)
- Github actions for CI testing on multiple platforms by https://github.com/philippeitis
- Updated ls parser to fix parsing error in OSX with -lR when there are empty folders
20200303 v1.8.0
- Added blkid command parser
- Added last and lastb command parser
- Added who command parser
- Added CSV file parser
- Added /etc/passwd file parser
- Added /etc/shadow file parser
- Added /etc/group file parser
- Added /etc/gshadow file parser
20200227 v1.7.5
- Updated ls parser to support filenames with newline characters
20200219 v1.7.4
- Updated ls parser to support multiple directories, globbing, and -R (recursive)
20200211 v1.7.3
- Add alternative 'magic' syntax: e.g. `jc ls -al`
- Options can now be condensed (e.g. -prq is equivalant to -p -r -q)
20200208 v1.7.2
- Include test fixtures in wheel and sdist
20200205 v1.7.1
- Add YAML file parser
- Add INI file parser
- Add XML file parser
- Add id parser (tested on linux and OSX)
- Add crontab file parser with user support (tested on linux)
- Add __version__ variable to parser modules
- Add exit code on error
- Updated history parser to output "line" as an integer
- Updated compatibility list for some parsers
- Bugfix in crontab file parser: header insertion was clobbering first row
- Just-in-time loading of parser modules instead of loading all at start
20191217 v1.6.1
- Add du parser (tested on linux and OSX)
- Add crontab parser (tested on linux and OSX)
- Add pip list parser (tested on linux and OSX)
- Add pip show parser (tested on linux and OSX)
- Add OSX support for the ifconfig, arp, df, mount, and uname parsers
- Add tests for ls, dig, ps, w, uptime on OSX
- Add about option
- Add universal parsers to refactor repetitive code
- Updated ifconfig parser to output 'state' as an array
20191117 v1.5.1
- Add ss parser
- Add stat parser

View File

@@ -4,31 +4,53 @@
cd jc
pydocmd simple jc+ > ../docs/readme.md
pydocmd simple utils+ > ../docs/utils.md
pydocmd simple jc.parsers.airport+ > ../docs/parsers/airport.md
pydocmd simple jc.parsers.airport_s+ > ../docs/parsers/airport_s.md
pydocmd simple jc.parsers.arp+ > ../docs/parsers/arp.md
pydocmd simple jc.parsers.blkid+ > ../docs/parsers/blkid.md
pydocmd simple jc.parsers.crontab+ > ../docs/parsers/crontab.md
pydocmd simple jc.parsers.crontab_u+ > ../docs/parsers/crontab_u.md
pydocmd simple jc.parsers.csv+ > ../docs/parsers/csv.md
pydocmd simple jc.parsers.df+ > ../docs/parsers/df.md
pydocmd simple jc.parsers.dig+ > ../docs/parsers/dig.md
pydocmd simple jc.parsers.du+ > ../docs/parsers/du.md
pydocmd simple jc.parsers.env+ > ../docs/parsers/env.md
pydocmd simple jc.parsers.file+ > ../docs/parsers/file.md
pydocmd simple jc.parsers.free+ > ../docs/parsers/free.md
pydocmd simple jc.parsers.fstab+ > ../docs/parsers/fstab.md
pydocmd simple jc.parsers.group+ > ../docs/parsers/group.md
pydocmd simple jc.parsers.gshadow+ > ../docs/parsers/gshadow.md
pydocmd simple jc.parsers.history+ > ../docs/parsers/history.md
pydocmd simple jc.parsers.hosts+ > ../docs/parsers/hosts.md
pydocmd simple jc.parsers.id+ > ../docs/parsers/id.md
pydocmd simple jc.parsers.ifconfig+ > ../docs/parsers/ifconfig.md
pydocmd simple jc.parsers.ini+ > ../docs/parsers/ini.md
pydocmd simple jc.parsers.iptables+ > ../docs/parsers/iptables.md
pydocmd simple jc.parsers.jobs+ > ../docs/parsers/jobs.md
pydocmd simple jc.parsers.last+ > ../docs/parsers/last.md
pydocmd simple jc.parsers.ls+ > ../docs/parsers/ls.md
pydocmd simple jc.parsers.lsblk+ > ../docs/parsers/lsblk.md
pydocmd simple jc.parsers.lsmod+ > ../docs/parsers/lsmod.md
pydocmd simple jc.parsers.lsof+ > ../docs/parsers/lsof.md
pydocmd simple jc.parsers.mount+ > ../docs/parsers/mount.md
pydocmd simple jc.parsers.netstat+ > ../docs/parsers/netstat.md
pydocmd simple jc.parsers.ntpq+ > ../docs/parsers/ntpq.md
pydocmd simple jc.parsers.passwd+ > ../docs/parsers/passwd.md
pydocmd simple jc.parsers.pip_list+ > ../docs/parsers/pip_list.md
pydocmd simple jc.parsers.pip_show+ > ../docs/parsers/pip_show.md
pydocmd simple jc.parsers.ps+ > ../docs/parsers/ps.md
pydocmd simple jc.parsers.route+ > ../docs/parsers/route.md
pydocmd simple jc.parsers.shadow+ > ../docs/parsers/shadow.md
pydocmd simple jc.parsers.ss+ > ../docs/parsers/ss.md
pydocmd simple jc.parsers.stat+ > ../docs/parsers/stat.md
pydocmd simple jc.parsers.systemctl+ > ../docs/parsers/systemctl.md
pydocmd simple jc.parsers.systemctl_lj+ > ../docs/parsers/systemctl_lj.md
pydocmd simple jc.parsers.systemctl_ls+ > ../docs/parsers/systemctl_ls.md
pydocmd simple jc.parsers.systemctl_luf+ > ../docs/parsers/systemctl_luf.md
pydocmd simple jc.parsers.timedatectl+ > ../docs/parsers/timedatectl.md
pydocmd simple jc.parsers.uname+ > ../docs/parsers/uname.md
pydocmd simple jc.parsers.uptime+ > ../docs/parsers/uptime.md
pydocmd simple jc.parsers.w+ > ../docs/parsers/w.md
pydocmd simple jc.parsers.who+ > ../docs/parsers/who.md
pydocmd simple jc.parsers.xml+ > ../docs/parsers/xml.md
pydocmd simple jc.parsers.yaml+ > ../docs/parsers/yaml.md

109
docs/parsers/airport.md Normal file
View File

@@ -0,0 +1,109 @@
# jc.parsers.airport
jc - JSON CLI output utility airport -I Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -I (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -I | jc --airport -p
{
"agrctlrssi": -66,
"agrextrssi": 0,
"agrctlnoise": -90,
"agrextnoise": 0,
"state": "running",
"op_mode": "station",
"lasttxrate": 195,
"maxrate": 867,
"lastassocstatus": 0,
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": 0,
"channel": "48,80"
}
$ airport -I | jc --airport -p -r
{
"agrctlrssi": "-66",
"agrextrssi": "0",
"agrctlnoise": "-90",
"agrextnoise": "0",
"state": "running",
"op_mode": "station",
"lasttxrate": "195",
"maxrate": "867",
"lastassocstatus": "0",
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": "0",
"channel": "48,80"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"agrctlrssi": integer,
"agrextrssi": integer,
"agrctlnoise": integer,
"agrextnoise": integer,
"state": string,
"op_mode": string,
"lasttxrate": integer,
"maxrate": integer,
"lastassocstatus": integer,
"802_11_auth": string,
"link_auth": string,
"bssid": string,
"ssid": string,
"mcs": integer,
"channel": string
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.

136
docs/parsers/airport_s.md Normal file
View File

@@ -0,0 +1,136 @@
# jc.parsers.airport_s
jc - JSON CLI output utility airport -s Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -s (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -s | jc --airport-s -p
[
{
"ssid": "DIRECT-4A-HP OfficeJet 3830",
"bssid": "00:67:eb:2a:a7:3b",
"rssi": -90,
"channel": "6",
"ht": true,
"cc": "--",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "Latitude38",
"bssid": "c0:ff:d5:d2:7a:f3",
"rssi": -85,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "xfinitywifi",
"bssid": "6e:e3:0e:b8:45:99",
"rssi": -83,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"NONE"
]
},
...
]
$ airport -s | jc --airport -p -r
[
{
"ssid": "DIRECT-F3-HP ENVY 5660 series",
"bssid": "b0:5a:da:6f:0a:d4",
"rssi": "-93",
"channel": "1",
"ht": "Y",
"cc": "--",
"security": "WPA2(PSK/AES/AES)"
},
{
"ssid": "YouAreInfected-5",
"bssid": "5c:e3:0e:c2:85:da",
"rssi": "-85",
"channel": "36",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
{
"ssid": "YuanFamily",
"bssid": "5c:e3:0e:b8:5f:9a",
"rssi": "-84",
"channel": "11",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"ssid": string,
"bssid": string,
"rssi": integer,
"channel": string,
"ht": boolean,
"cc": string,
"security": [
string,
]
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,7 +2,16 @@
jc - JSON CLI output utility arp Parser
Usage:
specify --arp as the first argument if the piped input is coming from arp
specify --arp as the first argument if the piped input is coming from:
arp
or
arp -a
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
@@ -78,6 +87,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -91,7 +105,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -119,5 +133,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

148
docs/parsers/blkid.md Normal file
View File

@@ -0,0 +1,148 @@
# jc.parsers.blkid
jc - JSON CLI output utility blkid Parser
Usage:
specify --blkid as the first argument if the piped input is coming from blkid
Compatibility:
'linux'
Examples:
$ blkid | jc --blkid -p
[
{
"device": "/dev/sda1",
"uuid": "05d927ab-5875-49e4-ada1-7f46cb32c932",
"type": "xfs"
},
{
"device": "/dev/sda2",
"uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
"type": "LVM2_member"
},
{
"device": "/dev/mapper/centos-root",
"uuid": "07d718ff-950c-4e5b-98f0-42a1147c77d9",
"type": "xfs"
},
{
"device": "/dev/mapper/centos-swap",
"uuid": "615eb89a-bcbf-46fd-80e3-c483ff5c931f",
"type": "swap"
}
]
$ sudo blkid -o udev -ip /dev/sda2 | jc --blkid -p
[
{
"id_fs_uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
"id_fs_uuid_enc": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
"id_fs_version": "LVM2\x20001",
"id_fs_type": "LVM2_member",
"id_fs_usage": "raid",
"id_iolimit_minimum_io_size": 512,
"id_iolimit_physical_sector_size": 512,
"id_iolimit_logical_sector_size": 512,
"id_part_entry_scheme": "dos",
"id_part_entry_type": "0x8e",
"id_part_entry_number": 2,
"id_part_entry_offset": 2099200,
"id_part_entry_size": 39843840,
"id_part_entry_disk": "8:0"
}
]
$ sudo blkid -ip /dev/sda1 | jc --blkid -p -r
[
{
"devname": "/dev/sda1",
"uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932",
"type": "xfs",
"usage": "filesystem",
"minimum_io_size": "512",
"physical_sector_size": "512",
"logical_sector_size": "512",
"part_entry_scheme": "dos",
"part_entry_type": "0x83",
"part_entry_flags": "0x80",
"part_entry_number": "1",
"part_entry_offset": "2048",
"part_entry_size": "2097152",
"part_entry_disk": "8:0"
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"device": string,
"uuid": string,
"type": string,
"usage": string,
"part_entry_scheme": string,
"part_entry_type": string,
"part_entry_flags": string,
"part_entry_number": integer,
"part_entry_offset": integer,
"part_entry_size": integer,
"part_entry_disk": string,
"id_fs_uuid": string,
"id_fs_uuid_enc": string,
"id_fs_version": string,
"id_fs_type": string,
"id_fs_usage": string,
"id_part_entry_scheme": string,
"id_part_entry_type": string,
"id_part_entry_flags": string,
"id_part_entry_number": integer,
"id_part_entry_offset": integer,
"id_part_entry_size": integer,
"id_iolimit_minimum_io_size": integer,
"id_iolimit_physical_sector_size": integer,
"id_iolimit_logical_sector_size": integer,
"id_part_entry_disk": string,
"minimum_io_size": integer,
"physical_sector_size": integer,
"logical_sector_size": integer
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

197
docs/parsers/crontab.md Normal file
View File

@@ -0,0 +1,197 @@
# jc.parsers.crontab
jc - JSON CLI output utility crontab command and file Parser
Usage:
specify --crontab as the first argument if the piped input is coming from crontab -l or a crontab file
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ crontab -l | jc --crontab -p
{
"variables": [
{
"name": "MAILTO",
"value": "root"
},
{
"name": "PATH",
"value": "/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/bash"
}
],
"schedule": [
{
"minute": [
"5"
],
"hour": [
"10-11",
"22"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"command": "/var/www/devdaily.com/bin/mk-new-links.php"
},
{
"minute": [
"30"
],
"hour": [
"4/2"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"command": "/var/www/devdaily.com/bin/create-all-backups.sh"
},
{
"occurrence": "yearly",
"command": "/home/maverick/bin/annual-maintenance"
},
{
"occurrence": "reboot",
"command": "/home/cleanup"
},
{
"occurrence": "monthly",
"command": "/home/maverick/bin/tape-backup"
}
]
}
$ cat /etc/crontab | jc --crontab -p -r
{
"variables": [
{
"name": "MAILTO",
"value": "root"
},
{
"name": "PATH",
"value": "/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/bash"
}
],
"schedule": [
{
"minute": "5",
"hour": "10-11,22",
"day_of_month": "*",
"month": "*",
"day_of_week": "*",
"command": "/var/www/devdaily.com/bin/mk-new-links.php"
},
{
"minute": "30",
"hour": "4/2",
"day_of_month": "*",
"month": "*",
"day_of_week": "*",
"command": "/var/www/devdaily.com/bin/create-all-backups.sh"
},
{
"occurrence": "yearly",
"command": "/home/maverick/bin/annual-maintenance"
},
{
"occurrence": "reboot",
"command": "/home/cleanup"
},
{
"occurrence": "monthly",
"command": "/home/maverick/bin/tape-backup"
}
]
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"variables": [
"name": string,
"value": string
],
"schedule": [
{
"occurrence" string,
"minute": [
string
],
"hour": [
string
],
"day_of_month": [
string
],
"month": [
string
],
"day_of_week": [
string
],
"occurrence": string,
"command": string
}
]
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.

199
docs/parsers/crontab_u.md Normal file
View File

@@ -0,0 +1,199 @@
# jc.parsers.crontab_u
jc - JSON CLI output utility crontab file Parser
Usage:
specify --crontab-u as the first argument if the piped input is coming from a crontab file with User specified
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ cat /etc/crontab | jc --crontab-u -p
{
"variables": [
{
"name": "PATH",
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/sh"
}
],
"schedule": [
{
"minute": [
"25"
],
"hour": [
"6"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
},
{
"minute": [
"47"
],
"hour": [
"6"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"7"
],
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
},
{
"minute": [
"52"
],
"hour": [
"6"
],
"day_of_month": [
"1"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
}
]
}
$ cat /etc/crontab | jc --crontab-u -p -r
{
"variables": [
{
"name": "PATH",
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/sh"
}
],
"schedule": [
{
"minute": "25",
"hour": "6",
"day_of_month": "*",
"month": "*",
"day_of_week": "*",
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
},
{
"minute": "47",
"hour": "6",
"day_of_month": "*",
"month": "*",
"day_of_week": "7",
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
},
{
"minute": "52",
"hour": "6",
"day_of_month": "1",
"month": "*",
"day_of_week": "*",
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
}
]
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"variables": [
"name": string,
"value": string
],
"schedule": [
{
"occurrence" string,
"minute": [
string
],
"hour": [
string
],
"day_of_month": [
string
],
"month": [
string
],
"day_of_week": [
string
],
"occurrence": string,
"user": string,
"command": string
}
]
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.

105
docs/parsers/csv.md Normal file
View File

@@ -0,0 +1,105 @@
# jc.parsers.csv
jc - JSON CLI output utility csv Parser
Usage:
specify --csv as the first argument if the piped input is coming from a csv file.
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.
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat homes.csv
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes"
142, 160, 28, 10, 5, 3, 60, 0.28, 3167
175, 180, 18, 8, 4, 1, 12, 0.43, 4033
129, 132, 13, 6, 3, 1, 41, 0.33, 1471
...
$ cat homes.csv | jc --csv -p
[
{
"Sell": "142",
"List": "160",
"Living": "28",
"Rooms": "10",
"Beds": "5",
"Baths": "3",
"Age": "60",
"Acres": "0.28",
"Taxes": "3167"
},
{
"Sell": "175",
"List": "180",
"Living": "18",
"Rooms": "8",
"Beds": "4",
"Baths": "1",
"Age": "12",
"Acres": "0.43",
"Taxes": "4033"
},
{
"Sell": "129",
"List": "132",
"Living": "13",
"Rooms": "6",
"Beds": "3",
"Baths": "1",
"Age": "41",
"Acres": "0.33",
"Taxes": "1471"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Each dictionary represents a row in the csv file:
[
{
csv file converted to a Dictionary
https://docs.python.org/3/library/csv.html
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,15 +2,20 @@
jc - JSON CLI output utility df Parser
Usage:
specify --df as the first argument if the piped input is coming from df
Compatibility:
'linux', 'darwin'
Examples:
$ df | jc --df -p
[
{
"filesystem": "devtmpfs",
"1k-blocks": 1918820,
"1k_blocks": 1918820,
"used": 0,
"available": 1918820,
"use_percent": 0,
@@ -18,7 +23,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": 1930668,
"1k_blocks": 1930668,
"used": 0,
"available": 1930668,
"use_percent": 0,
@@ -26,7 +31,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": 1930668,
"1k_blocks": 1930668,
"used": 11800,
"available": 1918868,
"use_percent": 1,
@@ -39,7 +44,7 @@ Examples:
[
{
"filesystem": "devtmpfs",
"1k-blocks": "1918820",
"1k_blocks": "1918820",
"used": "0",
"available": "1918820",
"use_percent": "0%",
@@ -47,7 +52,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": "1930668",
"1k_blocks": "1930668",
"used": "0",
"available": "1930668",
"use_percent": "0%",
@@ -55,7 +60,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": "1930668",
"1k_blocks": "1930668",
"used": "11800",
"available": "1918868",
"use_percent": "1%",
@@ -64,6 +69,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -77,17 +87,22 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"filesystem": string,
"size": string,
"1k-blocks": integer,
"used": integer,
"available": integer,
"use_percent": integer,
"mounted_on": string
"filesystem": string,
"size": string,
"1k_blocks": integer,
"512_blocks": integer,
"used": integer,
"available": integer,
"capacity_percent": integer,
"ifree": integer,
"iused": integer,
"use_percent": integer,
"iused_percent": integer,
"mounted_on": string
}
]
@@ -106,5 +121,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility dig Parser
Usage:
Specify --dig as the first argument if the piped input is coming from dig
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p
@@ -316,6 +321,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -329,7 +339,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -388,5 +398,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

115
docs/parsers/du.md Normal file
View File

@@ -0,0 +1,115 @@
# jc.parsers.du
jc - JSON CLI output utility du Parser
Usage:
specify --du as the first argument if the piped input is coming from du
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ du /usr | jc --du -p
[
{
"size": 104608,
"name": "/usr/bin"
},
{
"size": 56,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature"
},
{
"size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone"
},
{
"size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local"
},
{
"size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr"
},
{
"size": 1008,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu"
},
...
]
$ du /usr | jc --du -p -r
[
{
"size": "104608",
"name": "/usr/bin"
},
{
"size": "56",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature"
},
{
"size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone"
},
{
"size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local"
},
{
"size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr"
},
{
"size": "1008",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"size": integer,
"name": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility env Parser
Usage:
specify --env as the first argument if the piped input is coming from env
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ env | jc --env -p
@@ -44,6 +49,11 @@ Examples:
"_": "/usr/bin/env"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -57,7 +67,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -81,5 +91,6 @@ Parameters:
Returns:
dictionary raw or processed structured data
Dictionary of raw structured data or
list of dictionaries of processed structured data

90
docs/parsers/file.md Normal file
View File

@@ -0,0 +1,90 @@
# jc.parsers.file
jc - JSON CLI output utility file command Parser
Usage:
specify --file as the first argument if the piped input is coming from file.
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
$ file * | jc --file -p
[
{
"filename": "Applications",
"type": "directory"
},
{
"filename": "another file with spaces",
"type": "empty"
},
{
"filename": "argstest.py",
"type": "Python script text executable, ASCII text"
},
{
"filename": "blkid-p.out",
"type": "ASCII text"
},
{
"filename": "blkid-pi.out",
"type": "ASCII text, with very long lines"
},
{
"filename": "cd_catalog.xml",
"type": "XML 1.0 document text, ASCII text, with CRLF line terminators"
},
{
"filename": "centosserial.sh",
"type": "Bourne-Again shell script text executable, UTF-8 Unicode text"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"filename": string,
"type ": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility free Parser
Usage:
specify --free as the first argument if the piped input is coming from free
Compatibility:
'linux'
Examples:
$ free | jc --free -p
@@ -44,6 +49,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -57,7 +67,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -86,5 +96,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility fstab Parser
Usage:
specify --fstab as the first argument if the piped input is coming from a fstab file
Compatibility:
'linux'
Examples:
$ cat /etc/fstab | jc --fstab -p
@@ -62,6 +67,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -75,7 +85,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -103,5 +113,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

141
docs/parsers/group.md Normal file
View File

@@ -0,0 +1,141 @@
# jc.parsers.group
jc - JSON CLI output utility /etc/group file Parser
Usage:
specify --group as the first argument if the piped input is coming from /etc/group
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ cat /etc/group | jc --group -p
[
{
"group_name": "nobody",
"password": "*",
"gid": -2,
"members": []
},
{
"group_name": "nogroup",
"password": "*",
"gid": -1,
"members": []
},
{
"group_name": "wheel",
"password": "*",
"gid": 0,
"members": [
"root"
]
},
{
"group_name": "certusers",
"password": "*",
"gid": 29,
"members": [
"root",
"_jabber",
"_postfix",
"_cyrus",
"_calendar",
"_dovecot"
]
},
...
]
$ cat /etc/group | jc --group -p -r
[
{
"group_name": "nobody",
"password": "*",
"gid": "-2",
"members": [
""
]
},
{
"group_name": "nogroup",
"password": "*",
"gid": "-1",
"members": [
""
]
},
{
"group_name": "wheel",
"password": "*",
"gid": "0",
"members": [
"root"
]
},
{
"group_name": "certusers",
"password": "*",
"gid": "29",
"members": [
"root",
"_jabber",
"_postfix",
"_cyrus",
"_calendar",
"_dovecot"
]
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"group_name": string,
"password": string,
"gid": integer,
"members": [
string
]
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

109
docs/parsers/gshadow.md Normal file
View File

@@ -0,0 +1,109 @@
# jc.parsers.gshadow
jc - JSON CLI output utility /etc/gshadow file Parser
Usage:
specify --gshadow as the first argument if the piped input is coming from /etc/gshadow
Compatibility:
'linux', 'aix', 'freebsd'
Examples:
$ cat /etc/gshadow | jc --gshadow -p
[
{
"group_name": "root",
"password": "*",
"administrators": [],
"members": []
},
{
"group_name": "adm",
"password": "*",
"administrators": [],
"members": [
"syslog",
"joeuser"
]
},
...
]
$ cat /etc/gshadow | jc --gshadow -p -r
[
{
"group_name": "root",
"password": "*",
"administrators": [
""
],
"members": [
""
]
},
{
"group_name": "adm",
"password": "*",
"administrators": [
""
],
"members": [
"syslog",
"joeuser"
]
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"group_name": string,
"password": string,
"administrators": [
string
],
"members": [
string
]
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,26 +2,31 @@
jc - JSON CLI output utility history Parser
Usage:
specify --history as the first argument if the piped input is coming from history
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
$ history | jc --history -p
[
{
"line": "118",
"line": 118,
"command": "sleep 100"
},
{
"line": "119",
"line": 119,
"command": "ls /bin"
},
{
"line": "120",
"line": 120,
"command": "echo "hello""
},
{
"line": "121",
"line": 121,
"command": "docker images"
},
...
@@ -36,6 +41,11 @@ Examples:
...
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -49,11 +59,11 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"line": string,
"line": integer,
"command": string
}
]
@@ -73,5 +83,6 @@ Parameters:
Returns:
dictionary raw or processed structured data
Dictionary of raw structured data or
list of dictionaries of processed structured data

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility hosts Parser
Usage:
specify --hosts as the first argument if the piped input is coming from a hosts file
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat /etc/hosts | jc --hosts -p
@@ -53,6 +58,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -66,7 +76,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -92,5 +102,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

133
docs/parsers/id.md Normal file
View File

@@ -0,0 +1,133 @@
# jc.parsers.id
jc - JSON CLI output utility id Parser
Usage:
specify --id as the first argument if the piped input is coming from id
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ id | jc --id -p
{
"uid": {
"id": 1000,
"name": "joeuser"
},
"gid": {
"id": 1000,
"name": "joeuser"
},
"groups": [
{
"id": 1000,
"name": "joeuser"
},
{
"id": 10,
"name": "wheel"
}
],
"context": {
"user": "unconfined_u",
"role": "unconfined_r",
"type": "unconfined_t",
"level": "s0-s0:c0.c1023"
}
}
$ id | jc --id -p -r
{
"uid": {
"id": "1000",
"name": "joeuser"
},
"gid": {
"id": "1000",
"name": "joeuser"
},
"groups": [
{
"id": "1000",
"name": "joeuser"
},
{
"id": "10",
"name": "wheel"
}
],
"context": {
"user": "unconfined_u",
"role": "unconfined_r",
"type": "unconfined_t",
"level": "s0-s0:c0.c1023"
}
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"uid": {
"id": integer,
"name": string
},
"gid": {
"id": integer,
"name": string
},
"groups": [
{
"id": integer,
"name": string
},
{
"id": integer,
"name": string
}
],
"context": {
"user": string,
"role": string,
"type": string,
"level": string
}
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,10 +2,15 @@
jc - JSON CLI output utility ifconfig Parser
Usage:
specify --ifconfig as the first argument if the piped input is coming from ifconfig
no ifconfig options are supported.
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
$ ifconfig | jc --ifconfig -p
@@ -13,22 +18,29 @@ Examples:
{
"name": "ens33",
"flags": 4163,
"state": "UP,BROADCAST,RUNNING,MULTICAST",
"state": [
"UP",
"BROADCAST",
"RUNNING",
"MULTICAST"
],
"mtu": 1500,
"ipv4_addr": "192.168.71.138",
"ipv4_addr": "192.168.71.137",
"ipv4_mask": "255.255.255.0",
"ipv4_bcast": "192.168.71.255",
"ipv6_addr": "fe80::c1cb:715d:bc3e:b8a0",
"ipv6_mask": 64,
"ipv6_scope": "link",
"ipv6_scope": "0x20",
"mac_addr": "00:0c:29:3b:58:0e",
"type": "Ethernet",
"rx_packets": 6374,
"rx_packets": 8061,
"rx_bytes": 1514413,
"rx_errors": 0,
"rx_dropped": 0,
"rx_overruns": 0,
"rx_frame": 0,
"tx_packets": 3707,
"tx_packets": 4502,
"tx_bytes": 866622,
"tx_errors": 0,
"tx_dropped": 0,
"tx_overruns": 0,
@@ -39,22 +51,28 @@ Examples:
{
"name": "lo",
"flags": 73,
"state": "UP,LOOPBACK,RUNNING",
"state": [
"UP",
"LOOPBACK",
"RUNNING"
],
"mtu": 65536,
"ipv4_addr": "127.0.0.1",
"ipv4_mask": "255.0.0.0",
"ipv4_bcast": null,
"ipv6_addr": "::1",
"ipv6_mask": 128,
"ipv6_scope": "host",
"ipv6_scope": "0x10",
"mac_addr": null,
"type": "Local Loopback",
"rx_packets": 81,
"rx_packets": 73,
"rx_bytes": 6009,
"rx_errors": 0,
"rx_dropped": 0,
"rx_overruns": 0,
"rx_frame": 0,
"tx_packets": 81,
"tx_packets": 73,
"tx_bytes": 6009,
"tx_errors": 0,
"tx_dropped": 0,
"tx_overruns": 0,
@@ -71,20 +89,22 @@ Examples:
"flags": "4163",
"state": "UP,BROADCAST,RUNNING,MULTICAST",
"mtu": "1500",
"ipv4_addr": "192.168.71.135",
"ipv4_addr": "192.168.71.137",
"ipv4_mask": "255.255.255.0",
"ipv4_bcast": "192.168.71.255",
"ipv6_addr": "fe80::c1cb:715d:bc3e:b8a0",
"ipv6_mask": "64",
"ipv6_scope": "link",
"ipv6_scope": "0x20",
"mac_addr": "00:0c:29:3b:58:0e",
"type": "Ethernet",
"rx_packets": "26348",
"rx_packets": "8061",
"rx_bytes": "1514413",
"rx_errors": "0",
"rx_dropped": "0",
"rx_overruns": "0",
"rx_frame": "0",
"tx_packets": "5308",
"tx_packets": "4502",
"tx_bytes": "866622",
"tx_errors": "0",
"tx_dropped": "0",
"tx_overruns": "0",
@@ -102,15 +122,17 @@ Examples:
"ipv4_bcast": null,
"ipv6_addr": "::1",
"ipv6_mask": "128",
"ipv6_scope": "host",
"ipv6_scope": "0x10",
"mac_addr": null,
"type": "Local Loopback",
"rx_packets": "64",
"rx_packets": "73",
"rx_bytes": "6009",
"rx_errors": "0",
"rx_dropped": "0",
"rx_overruns": "0",
"rx_frame": "0",
"tx_packets": "64",
"tx_packets": "73",
"tx_bytes": "6009",
"tx_errors": "0",
"tx_dropped": "0",
"tx_overruns": "0",
@@ -120,6 +142,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -133,13 +160,15 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"name": string,
"flags": integer,
"state": string,
"state": [
string
],
"mtu": integer,
"ipv4_addr": string,
"ipv4_mask": string,
@@ -150,11 +179,13 @@ Returns:
"mac_addr": string,
"type": string,
"rx_packets": integer,
"rx_bytes": integer,
"rx_errors": integer,
"rx_dropped": integer,
"rx_overruns": integer,
"rx_frame": integer,
"tx_packets": integer,
"tx_bytes": integer,
"tx_errors": integer,
"tx_dropped": integer,
"tx_overruns": integer,
@@ -179,5 +210,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

87
docs/parsers/ini.md Normal file
View File

@@ -0,0 +1,87 @@
# jc.parsers.ini
jc - JSON CLI output utility INI Parser
Usage:
specify --ini as the first argument if the piped input is coming from an INI file
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat example.ini
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
$ cat example.ini | jc --ini -p
{
"bitbucket.org": {
"serveraliveinterval": "45",
"compression": "yes",
"compressionlevel": "9",
"forwardx11": "yes",
"user": "hg"
},
"topsecret.server.com": {
"serveraliveinterval": "45",
"compression": "yes",
"compressionlevel": "9",
"forwardx11": "no",
"port": "50022"
}
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary representing an ini document:
{
ini document converted to a dictionary
see configparser standard library documentation for more details
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary representing the ini file

View File

@@ -2,10 +2,15 @@
jc - JSON CLI output utility ipables Parser
Usage:
Specify --iptables as the first argument if the piped input is coming from iptables
Supports -vLn and --line-numbers for all tables
Compatibility:
'linux'
Examples:
$ sudo iptables --line-numbers -v -L -t nat | jc --iptables -p
@@ -126,6 +131,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -139,7 +149,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -177,5 +187,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,10 +2,15 @@
jc - JSON CLI output utility jobs Parser
Usage:
specify --jobs as the first argument if the piped input is coming from jobs
Also supports the -l option
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Example:
$ jobs -l | jc --jobs -p
@@ -68,6 +73,11 @@ Example:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -81,7 +91,8 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"job_number": integer,
@@ -107,5 +118,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

118
docs/parsers/last.md Normal file
View File

@@ -0,0 +1,118 @@
# jc.parsers.last
jc - JSON CLI output utility last Parser
Usage:
specify --last as the first argument if the piped input is coming from last or lastb
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ last | jc --last -p
[
{
"user": "kbrazil",
"tty": "ttys002",
"hostname": null,
"login": "Thu Feb 27 14:31",
"logout": "still logged in"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": null,
"login": "Thu Feb 27 10:38",
"logout": "10:38",
"duration": "00:00"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": null,
"login": "Thu Feb 27 10:18",
"logout": "10:18",
"duration": "00:00"
},
...
]
$ last | jc --last -p -r
[
{
"user": "kbrazil",
"tty": "ttys002",
"hostname": "-",
"login": "Thu Feb 27 14:31",
"logout": "still_logged_in"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": "-",
"login": "Thu Feb 27 10:38",
"logout": "10:38",
"duration": "00:00"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": "-",
"login": "Thu Feb 27 10:18",
"logout": "10:18",
"duration": "00:00"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"user": string,
"tty": string,
"hostname": string,
"login": string,
"logout": string,
"duration": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -1,15 +1,25 @@
# jc.parsers.ls
jc - JSON CLI output utility ls Parser
Note: The -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 -l or -b is not used.
Usage:
specify --ls as the first argument if the piped input is coming from ls
ls options supported:
- None
- la
- h file sizes will be available in text form with -r but larger file sizes
with human readable suffixes will be converted to Null in default view
since the parser attempts to convert this field to an integer.
-lbaR
--time-style=full-iso
-h file sizes will be available in text form with -r but larger file sizes
with human readable suffixes will be converted to Null in default view
since the parser attempts to convert this field to an integer.
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
@@ -135,6 +145,11 @@ Examples:
"date": "May 3 2019"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -148,13 +163,14 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"filename": string,
"flags": string,
"links": integer,
"parent": string,
"owner": string,
"group": string,
"size": integer,
@@ -177,5 +193,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility lsblk Parser
Usage:
specify --lsblk as the first argument if the piped input is coming from lsblk
Compatibility:
'linux'
Examples:
$ lsblk | jc --lsblk -p
@@ -207,6 +212,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -220,7 +230,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -282,5 +292,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility lsmod Parser
Usage:
specify --lsmod as the first argument if the piped input is coming from lsmod
Compatibility:
'linux'
Examples:
$ lsmod | jc --lsmod -p
@@ -98,6 +103,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -111,7 +121,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -139,5 +149,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility lsof Parser
Usage:
specify --lsof as the first argument if the piped input is coming from lsof
Compatibility:
'linux'
Examples:
$ sudo lsof | jc --lsof -p
@@ -88,6 +93,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -101,7 +111,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -133,5 +143,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility mount Parser
Usage:
specify --mount as the first argument if the piped input is coming from mount
Compatibility:
'linux', 'darwin'
Example:
$ mount | jc --mount -p
@@ -48,6 +53,11 @@ Example:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -61,7 +71,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -89,5 +99,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility netstat Parser
Usage:
Specify --netstat as the first argument if the piped input is coming from netstat
Compatibility:
'linux'
Examples:
$ sudo netstat -apee | jc --netstat -p
@@ -304,6 +309,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -317,7 +327,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -361,5 +371,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

235
docs/parsers/ntpq.md Normal file
View File

@@ -0,0 +1,235 @@
# jc.parsers.ntpq
jc - JSON CLI output utility ntpq Parser
Usage:
specify --ntpq as the first argument if the piped input is coming from ntpq -p
Compatibility:
'linux'
Examples:
$ ntpq -p | jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 1,
"poll": 64,
"reach": 1,
"delay": 23.399,
"offset": -2.805,
"jitter": 2.131,
"state": null
},
{
"remote": "ntp.wdc1.us.lea",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 93.053,
"offset": -0.807,
"jitter": 2.839,
"state": null
},
{
"remote": "clock.team-cymr",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 70.337,
"offset": -2.909,
"jitter": 2.6,
"state": null
},
{
"remote": "mirror1.sjc02.s",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 2,
"poll": 64,
"reach": 1,
"delay": 29.325,
"offset": 1.044,
"jitter": 4.069,
"state": null,
}
]
$ ntpq -pn| jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 66,
"poll": 64,
"reach": 377,
"delay": 22.69,
"offset": -0.392,
"jitter": 2.085,
"state": "+"
},
{
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 90.805,
"offset": 2.84,
"jitter": 1.908,
"state": "-"
},
{
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": 64,
"poll": 64,
"reach": 377,
"delay": 68.699,
"offset": -0.61,
"jitter": 2.576,
"state": "+"
},
{
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 22.654,
"offset": 0.231,
"jitter": 1.964,
"state": "*"
}
]
$ ntpq -pn| jc --ntpq -p -r
[
{
"s": "+",
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": "2",
"t": "u",
"when": "66",
"poll": "64",
"reach": "377",
"delay": "22.690",
"offset": "-0.392",
"jitter": "2.085"
},
{
"s": "-",
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "90.805",
"offset": "2.840",
"jitter": "1.908"
},
{
"s": "+",
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": "2",
"t": "u",
"when": "64",
"poll": "64",
"reach": "377",
"delay": "68.699",
"offset": "-0.610",
"jitter": "2.576"
},
{
"s": "*",
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "22.654",
"offset": "0.231",
"jitter": "1.964"
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"state": string, # space/~ converted to null
"remote": string,
"refid": string,
"st": integer,
"t": string,
"when": integer, # - converted to null
"poll": integer,
"reach": integer,
"delay": float,
"offset": float,
"jitter": float
},
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

126
docs/parsers/passwd.md Normal file
View File

@@ -0,0 +1,126 @@
# jc.parsers.passwd
jc - JSON CLI output utility /etc/passwd file Parser
Usage:
specify --passwd as the first argument if the piped input is coming from /etc/passwd
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ cat /etc/passwd | jc --passwd -p
[
{
"username": "nobody",
"password": "*",
"uid": -2,
"gid": -2,
"comment": "Unprivileged User",
"home": "/var/empty",
"shell": "/usr/bin/false"
},
{
"username": "root",
"password": "*",
"uid": 0,
"gid": 0,
"comment": "System Administrator",
"home": "/var/root",
"shell": "/bin/sh"
},
{
"username": "daemon",
"password": "*",
"uid": 1,
"gid": 1,
"comment": "System Services",
"home": "/var/root",
"shell": "/usr/bin/false"
},
...
]
$ cat /etc/passwd | jc --passwd -p -r
[
{
"username": "nobody",
"password": "*",
"uid": "-2",
"gid": "-2",
"comment": "Unprivileged User",
"home": "/var/empty",
"shell": "/usr/bin/false"
},
{
"username": "root",
"password": "*",
"uid": "0",
"gid": "0",
"comment": "System Administrator",
"home": "/var/root",
"shell": "/bin/sh"
},
{
"username": "daemon",
"password": "*",
"uid": "1",
"gid": "1",
"comment": "System Services",
"home": "/var/root",
"shell": "/usr/bin/false"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"username": string,
"password": string,
"uid": integer,
"gid": integer,
"comment": string,
"home": string,
"shell": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

75
docs/parsers/pip_list.md Normal file
View File

@@ -0,0 +1,75 @@
# jc.parsers.pip_list
jc - JSON CLI output utility pip-list Parser
Usage:
specify --pip-list as the first argument if the piped input is coming from pip list
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ pip list | jc --pip-list -p
[
{
"package": "ansible",
"version": "2.8.5"
},
{
"package": "antlr4-python3-runtime",
"version": "4.7.2"
},
{
"package": "asn1crypto",
"version": "0.24.0"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"package": string,
"version": string,
"location": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

94
docs/parsers/pip_show.md Normal file
View File

@@ -0,0 +1,94 @@
# jc.parsers.pip_show
jc - JSON CLI output utility pip-show Parser
Usage:
specify --pip-show as the first argument if the piped input is coming from pip show
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ pip show wrapt jc wheel | jc --pip-show -p
[
{
"name": "wrapt",
"version": "1.11.2",
"summary": "Module for decorators, wrappers and monkey patching.",
"home_page": "https://github.com/GrahamDumpleton/wrapt",
"author": "Graham Dumpleton",
"author_email": "Graham.Dumpleton@gmail.com",
"license": "BSD",
"location": "/usr/local/lib/python3.7/site-packages",
"requires": null,
"required_by": "astroid"
},
{
"name": "wheel",
"version": "0.33.4",
"summary": "A built-package format for Python.",
"home_page": "https://github.com/pypa/wheel",
"author": "Daniel Holth",
"author_email": "dholth@fastmail.fm",
"license": "MIT",
"location": "/usr/local/lib/python3.7/site-packages",
"requires": null,
"required_by": null
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"name": string,
"version": string,
"summary": string,
"home_page": string,
"author": string,
"author_email": string,
"license": string,
"location": string,
"requires": string,
"required_by": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,12 +2,17 @@
jc - JSON CLI output utility ps Parser
Usage:
specify --ps as the first argument if the piped input is coming from ps
ps options supported:
- ef
- axu
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
$ ps -ef | jc --ps -p
@@ -168,6 +173,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -181,7 +191,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -190,7 +200,8 @@ Returns:
"ppid": integer,
"c": integer,
"stime": string,
"tty": string, # ? = Null
"tty": string, # ? or ?? = Null
"tt": string, # ?? = Null
"time": string,
"cmd": string,
"user": string,
@@ -219,5 +230,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility route Parser
Usage:
specify --route as the first argument if the piped input is coming from route
Compatibility:
'linux'
Examples:
$ route -ee | jc --route -p
@@ -92,6 +97,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -105,7 +115,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -138,5 +148,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

133
docs/parsers/shadow.md Normal file
View File

@@ -0,0 +1,133 @@
# jc.parsers.shadow
jc - JSON CLI output utility /etc/shadow file Parser
Usage:
specify --shadow as the first argument if the piped input is coming from /etc/shadow
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ sudo cat /etc/shadow | jc --shadow -p
[
{
"username": "root",
"password": "*",
"last_changed": 18113,
"minimum": 0,
"maximum": 99999,
"warn": 7,
"inactive": null,
"expire": null
},
{
"username": "daemon",
"password": "*",
"last_changed": 18113,
"minimum": 0,
"maximum": 99999,
"warn": 7,
"inactive": null,
"expire": null
},
{
"username": "bin",
"password": "*",
"last_changed": 18113,
"minimum": 0,
"maximum": 99999,
"warn": 7,
"inactive": null,
"expire": null
},
...
]
$ sudo cat /etc/shadow | jc --shadow -p -r
[
{
"username": "root",
"password": "*",
"last_changed": "18113",
"minimum": "0",
"maximum": "99999",
"warn": "7",
"inactive": "",
"expire": ""
},
{
"username": "daemon",
"password": "*",
"last_changed": "18113",
"minimum": "0",
"maximum": "99999",
"warn": "7",
"inactive": "",
"expire": ""
},
{
"username": "bin",
"password": "*",
"last_changed": "18113",
"minimum": "0",
"maximum": "99999",
"warn": "7",
"inactive": "",
"expire": ""
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"username": string,
"password": string,
"last_changed": integer,
"minimum": integer,
"maximum": integer,
"warn": integer,
"inactive": integer,
"expire": integer
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -2,11 +2,17 @@
jc - JSON CLI output utility ss Parser
Usage:
specify --ss as the first argument if the piped input is coming from ss
Limitations:
Extended information options like -e and -p are not supported and may cause parsing irregularities
Compatibility:
'linux'
Examples:
$ sudo ss -a | jc --ss -p
@@ -241,6 +247,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -254,7 +265,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -293,5 +304,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -1,8 +1,13 @@
# jc.parsers.stat
jc - JSON CLI output utility stats Parser
jc - JSON CLI output utility stat Parser
Usage:
specify --stats as the first argument if the piped input is coming from stats
specify --stat as the first argument if the piped input is coming from stat
Compatibility:
'linux'
Examples:
@@ -96,6 +101,11 @@ Examples:
..
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -109,7 +119,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -150,5 +160,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility systemctl Parser
Usage:
specify --systemctl as the first argument if the piped input is coming from systemctl
Compatibility:
'linux'
Examples:
$ systemctl -a | jc --systemctl -p
@@ -32,6 +37,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -45,7 +55,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -72,5 +82,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility systemctl-lj Parser
Usage:
specify --systemctl-lj as the first argument if the piped input is coming from systemctl list-jobs
Compatibility:
'linux'
Examples:
$ systemctl list-jobs| jc --systemctl-lj -p
@@ -51,6 +56,11 @@ Examples:
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -64,7 +74,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -90,5 +100,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility systemctl-ls Parser
Usage:
specify --systemctl-ls as the first argument if the piped input is coming from systemctl list-sockets
Compatibility:
'linux'
Examples:
$ systemctl list-sockets | jc --systemctl-ls -p
@@ -26,6 +31,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -39,7 +49,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -64,5 +74,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility systemctl-luf Parser
Usage:
specify --systemctl-luf as the first argument if the piped input is coming from systemctl list-unit-files
Compatibility:
'linux'
Examples:
$ systemctl list-unit-files | jc --systemctl-luf -p
@@ -23,6 +28,11 @@ Examples:
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -36,7 +46,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -60,5 +70,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

View File

@@ -0,0 +1,87 @@
# jc.parsers.timedatectl
jc - JSON CLI output utility timedatectl Parser
Usage:
specify --timedatectl as the first argument if the piped input is coming from timedatectl or timedatectl status
Compatibility:
'linux'
Examples:
$ timedatectl | jc --timedatectl -p
{
"local_time": "Tue 2020-03-10 17:53:21 PDT",
"universal_time": "Wed 2020-03-11 00:53:21 UTC",
"rtc_time": "Wed 2020-03-11 00:53:21",
"time_zone": "America/Los_Angeles (PDT, -0700)",
"ntp_enabled": true,
"ntp_synchronized": true,
"rtc_in_local_tz": false,
"dst_active": true
}
$ timedatectl | jc --timedatectl -p -r
{
"local_time": "Tue 2020-03-10 17:53:21 PDT",
"universal_time": "Wed 2020-03-11 00:53:21 UTC",
"rtc_time": "Wed 2020-03-11 00:53:21",
"time_zone": "America/Los_Angeles (PDT, -0700)",
"ntp_enabled": "yes",
"ntp_synchronized": "yes",
"rtc_in_local_tz": "no",
"dst_active": "yes"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"local_time": string,
"universal_time": string,
"rtc_time": string,
"time_zone": string,
"ntp_enabled": boolean,
"ntp_synchronized": boolean,
"system_clock_synchronized": boolean,
"systemd-timesyncd.service_active": boolean,
"rtc_in_local_tz": boolean,
"dst_active": boolean
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.

View File

@@ -2,11 +2,17 @@
jc - JSON CLI output utility uname Parser
Usage:
specify --uname as the first argument if the piped input is coming from uname
Limitations:
must use 'uname -a'
Compatibility:
'linux', 'darwin'
Example:
$ uname -a | jc --uname -p
@@ -21,6 +27,11 @@ Example:
"kernel_version": "#74-Ubuntu SMP Tue Sep 17 17:06:04 UTC 2019"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -34,7 +45,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
Dictionary. Structured data with the following schema:
{
"kernel_name": string,
@@ -62,5 +73,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
Dictionary. Raw or processed structured data.

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility uptime Parser
Usage:
specify --uptime as the first argument if the piped input is coming from uptime
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Example:
$ uptime | jc --uptime -p
@@ -26,6 +31,11 @@ Example:
"load_15m": "0.05"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -39,7 +49,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
Dictionary. Structured data with the following schema:
{
"time": string,
@@ -65,5 +75,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
Dictionary. Raw or processed structured data

View File

@@ -2,8 +2,13 @@
jc - JSON CLI output utility w Parser
Usage:
specify --w as the first argument if the piped input is coming from w
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
$ w | jc --w -p
@@ -74,6 +79,11 @@ Examples:
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
@@ -87,7 +97,7 @@ Parameters:
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -117,5 +127,5 @@ Parameters:
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.

152
docs/parsers/who.md Normal file
View File

@@ -0,0 +1,152 @@
# jc.parsers.who
jc - JSON CLI output utility who Parser
Usage:
specify --who as the first argument if the piped input is coming from who
accepts any of the following who options (or no options): -aTH
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
$ who -a | jc --who -p
[
{
"event": "reboot",
"time": "Feb 7 23:31",
"pid": 1
},
{
"user": "joeuser",
"writeable_tty": "-",
"tty": "console",
"time": "Feb 7 23:32",
"idle": "old",
"pid": 105
},
{
"user": "joeuser",
"writeable_tty": "+",
"tty": "ttys000",
"time": "Feb 13 16:44",
"idle": ".",
"pid": 51217,
"comment": "term=0 exit=0"
},
{
"user": "joeuser",
"writeable_tty": "?",
"tty": "ttys003",
"time": "Feb 28 08:59",
"idle": "01:36",
"pid": 41402
},
{
"user": "joeuser",
"writeable_tty": "+",
"tty": "ttys004",
"time": "Mar 1 16:35",
"idle": ".",
"pid": 15679,
"from": "192.168.1.5"
}
]
$ who -a | jc --who -p -r
[
{
"event": "reboot",
"time": "Feb 7 23:31",
"pid": "1"
},
{
"user": "joeuser",
"writeable_tty": "-",
"tty": "console",
"time": "Feb 7 23:32",
"idle": "old",
"pid": "105"
},
{
"user": "joeuser",
"writeable_tty": "+",
"tty": "ttys000",
"time": "Feb 13 16:44",
"idle": ".",
"pid": "51217",
"comment": "term=0 exit=0"
},
{
"user": "joeuser",
"writeable_tty": "?",
"tty": "ttys003",
"time": "Feb 28 08:59",
"idle": "01:36",
"pid": "41402"
},
{
"user": "joeuser",
"writeable_tty": "+",
"tty": "ttys004",
"time": "Mar 1 16:35",
"idle": ".",
"pid": "15679",
"from": "192.168.1.5"
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"user": string,
"event": string,
"writeable_tty": string,
"tty": string,
"time": string,
"idle": string,
"pid": integer,
"from": string,
"comment": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

99
docs/parsers/xml.md Normal file
View File

@@ -0,0 +1,99 @@
# jc.parsers.xml
jc - JSON CLI output utility XML Parser
Usage:
specify --xml as the first argument if the piped input is coming from an XML file
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat cd_catalog.xml
<?xml version="1.0" encoding="UTF-8"?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
...
$ cat cd_catalog.xml | jc --xml -p
{
"CATALOG": {
"CD": [
{
"TITLE": "Empire Burlesque",
"ARTIST": "Bob Dylan",
"COUNTRY": "USA",
"COMPANY": "Columbia",
"PRICE": "10.90",
"YEAR": "1985"
},
{
"TITLE": "Hide your heart",
"ARTIST": "Bonnie Tyler",
"COUNTRY": "UK",
"COMPANY": "CBS Records",
"PRICE": "9.90",
"YEAR": "1988"
},
...
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary representing an XML document:
{
XML Document converted to a Dictionary
See https://github.com/martinblech/xmltodict for details
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.

113
docs/parsers/yaml.md Normal file
View File

@@ -0,0 +1,113 @@
# jc.parsers.yaml
jc - JSON CLI output utility YAML Parser
Usage:
specify --yaml as the first argument if the piped input is coming from a YAML file
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat istio-mtls-permissive.yaml
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: "default"
spec:
peers:
- mtls: {}
---
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "default"
namespace: "default"
spec:
host: "*.default.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
$ cat istio-mtls-permissive.yaml | jc --yaml -p
[
{
"apiVersion": "authentication.istio.io/v1alpha1",
"kind": "Policy",
"metadata": {
"name": "default",
"namespace": "default"
},
"spec": {
"peers": [
{
"mtls": {}
}
]
}
},
{
"apiVersion": "networking.istio.io/v1alpha3",
"kind": "DestinationRule",
"metadata": {
"name": "default",
"namespace": "default"
},
"spec": {
"host": "*.default.svc.cluster.local",
"trafficPolicy": {
"tls": {
"mode": "ISTIO_MUTUAL"
}
}
}
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Each dictionary represents a YAML document:
[
{
YAML Document converted to a Dictionary
See https://pypi.org/project/ruamel.yaml for details
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

397
jc/cli.py
View File

@@ -1,182 +1,323 @@
#!/usr/bin/env python3
"""jc - JSON CLI output utility
JC cli module
"""
import sys
import os
import shlex
import importlib
import textwrap
import signal
import json
import jc.utils
import jc.parsers.arp
import jc.parsers.df
import jc.parsers.dig
import jc.parsers.env
import jc.parsers.free
import jc.parsers.fstab
import jc.parsers.history
import jc.parsers.hosts
import jc.parsers.ifconfig
import jc.parsers.iptables
import jc.parsers.jobs
import jc.parsers.ls
import jc.parsers.lsblk
import jc.parsers.lsmod
import jc.parsers.lsof
import jc.parsers.mount
import jc.parsers.netstat
import jc.parsers.ps
import jc.parsers.route
import jc.parsers.ss
import jc.parsers.stat
import jc.parsers.systemctl
import jc.parsers.systemctl_lj
import jc.parsers.systemctl_ls
import jc.parsers.systemctl_luf
import jc.parsers.uname
import jc.parsers.uptime
import jc.parsers.w
class info():
version = '1.9.0'
description = 'jc cli output JSON conversion tool'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
__version__ = info.version
parsers = [
'airport',
'airport-s',
'arp',
'blkid',
'crontab',
'crontab-u',
'csv',
'df',
'dig',
'du',
'env',
'file',
'free',
'fstab',
'group',
'gshadow',
'history',
'hosts',
'id',
'ifconfig',
'ini',
'iptables',
'jobs',
'last',
'ls',
'lsblk',
'lsmod',
'lsof',
'mount',
'netstat',
'ntpq',
'passwd',
'pip-list',
'pip-show',
'ps',
'route',
'shadow',
'ss',
'stat',
'systemctl',
'systemctl-lj',
'systemctl-ls',
'systemctl-luf',
'timedatectl',
'uname',
'uptime',
'w',
'who',
'xml',
'yaml'
]
def ctrlc(signum, frame):
exit()
"""exit with error on SIGINT"""
sys.exit(1)
def parser_shortname(parser_argument):
"""short name of the parser with dashes and no -- prefix"""
return parser_argument[2:]
def parser_argument(parser):
"""short name of the parser with dashes and with -- prefix"""
return f'--{parser}'
def parser_mod_shortname(parser):
"""short name of the parser's module name (no -- prefix and dashes converted to underscores)"""
return parser.replace('--', '').replace('-', '_')
def parser_module(parser):
"""import the module just in time and return the module object"""
importlib.import_module('jc.parsers.' + parser_mod_shortname(parser))
return getattr(jc.parsers, parser_mod_shortname(parser))
def parsers_text(indent=0, pad=0):
"""return the argument and description information from each parser"""
ptext = ''
for parser in parsers:
parser_arg = parser_argument(parser)
parser_mod = parser_module(parser)
if hasattr(parser_mod, 'info'):
parser_desc = parser_mod.info.description
padding = pad - len(parser_arg)
padding_char = ' '
indent_text = padding_char * indent
padding_text = padding_char * padding
ptext += indent_text + parser_arg + padding_text + parser_desc + '\n'
return ptext
def about_jc():
"""return jc info and the contents of each parser.info as a dictionary"""
parser_list = []
for parser in parsers:
parser_mod = parser_module(parser)
if hasattr(parser_mod, 'info'):
info_dict = {}
info_dict['name'] = parser_mod.__name__.split('.')[-1]
info_dict['argument'] = parser_argument(parser)
parser_entry = vars(parser_mod.info)
for k, v in parser_entry.items():
if not k.startswith('__'):
info_dict[k] = v
parser_list.append(info_dict)
return {
'name': 'jc',
'version': info.version,
'description': info.description,
'author': info.author,
'author_email': info.author_email,
'parser_count': len(parser_list),
'parsers': parser_list
}
def helptext(message):
"""return the help text with the list of parsers"""
parsers_string = parsers_text(indent=12, pad=17)
helptext_string = f'''
jc: {message}
Usage: jc PARSER [OPTIONS]
Usage: COMMAND | jc PARSER [OPTIONS]
or magic syntax:
jc [OPTIONS] COMMAND
Parsers:
--arp arp parser
--df df parser
--dig dig parser
--env env parser
--free free parser
--fstab /etc/fstab file parser
--history history parser
--hosts /etc/hosts file parser
--ifconfig iconfig parser
--iptables iptables parser
--jobs jobs parser
--ls ls parser
--lsblk lsblk parser
--lsmod lsmod parser
--lsof lsof parser
--mount mount parser
--netstat netstat parser
--ps ps parser
--route route parser
--ss ss parser
--stat stat parser
--systemctl systemctl parser
--systemctl-lj systemctl list-jobs parser
--systemctl-ls systemctl list-sockets parser
--systemctl-luf systemctl list-unit-files parser
--uname uname -a parser
--uptime uptime parser
--w w parser
{parsers_string}
Options:
-d debug - show trace messages
-p pretty print output
-q quiet - suppress warnings
-r raw JSON output
-a about jc
-d debug - show trace messages
-p pretty print output
-q quiet - suppress warnings
-r raw JSON output
Example:
ls -al | jc --ls -p
or using the magic syntax:
jc -p ls -al
'''
print(textwrap.dedent(helptext_string), file=sys.stderr)
def json_out(data, pretty=False):
if pretty:
print(json.dumps(data, indent=2))
else:
print(json.dumps(data))
def generate_magic_command(args):
"""
Returns a tuple with a boolean and a command, where the boolean signifies that
the command is valid, and the command is either a command string or None.
"""
# Parse with magic syntax: jc -p ls -al
if len(args) <= 1 or args[1].startswith('--'):
return False, None
# correctly parse escape characters and spaces with shlex
args_given = ' '.join(map(shlex.quote, args[1:])).split()
options = []
# find the options
for arg in list(args_given):
# parser found - use standard syntax
if arg.startswith('--'):
return False, None
# option found - populate option list
elif arg.startswith('-'):
options.extend(args_given.pop(0)[1:])
# command found if iterator didn't already stop - stop iterating
else:
break
# all options popped and no command found - for case like 'jc -a'
if len(args_given) == 0:
return False, None
magic_dict = {}
parser_info = about_jc()['parsers']
# Create a dictionary of magic_commands to their respective parsers.
for entry in parser_info:
# Update the dict with all of the magic commands for this parser, if they exist.
magic_dict.update({mc: entry['argument'] for mc in entry.get('magic_commands', [])})
# find the command and parser
one_word_command = args_given[0]
two_word_command = ' '.join(args_given[0:2])
# Try to get a parser for two_word_command, otherwise get one for one_word_command
found_parser = magic_dict.get(two_word_command, magic_dict.get(one_word_command))
# construct a new command line using the standard syntax: COMMAND | jc --PARSER -OPTIONS
run_command = ' '.join(args_given)
if found_parser:
cmd_options = ('-' + ''.join(options)) if options else ''
return True, ' '.join([run_command, '|', 'jc', found_parser, cmd_options])
else:
return False, run_command
def magic():
valid_command, run_command = generate_magic_command(sys.argv)
if valid_command:
os.system(run_command)
exit()
elif run_command is None:
return
else:
helptext(f'parser not found for "{run_command}"')
sys.exit(1)
def main():
# break on ctrl-c keyboard interrupt
signal.signal(signal.SIGINT, ctrlc)
# try magic syntax first: e.g. jc -p ls -al
magic()
options = []
# options
for opt in sys.argv:
if opt.startswith('-') and not opt.startswith('--'):
options.extend(opt[1:])
debug = 'd' in options
pretty = 'p' in options
quiet = 'q' in options
raw = 'r' in options
if 'a' in options:
json_out(about_jc(), pretty=pretty)
exit()
if sys.stdin.isatty():
helptext('missing piped data')
exit()
sys.exit(1)
data = sys.stdin.read()
debug = False
pretty = False
quiet = False
raw = False
# options
if '-d' in sys.argv:
debug = True
if '-p' in sys.argv:
pretty = True
if '-q' in sys.argv:
quiet = True
if '-r' in sys.argv:
raw = True
# parsers
parser_map = {
'--arp': jc.parsers.arp.parse,
'--df': jc.parsers.df.parse,
'--dig': jc.parsers.dig.parse,
'--env': jc.parsers.env.parse,
'--free': jc.parsers.free.parse,
'--fstab': jc.parsers.fstab.parse,
'--history': jc.parsers.history.parse,
'--hosts': jc.parsers.hosts.parse,
'--ifconfig': jc.parsers.ifconfig.parse,
'--iptables': jc.parsers.iptables.parse,
'--jobs': jc.parsers.jobs.parse,
'--ls': jc.parsers.ls.parse,
'--lsblk': jc.parsers.lsblk.parse,
'--lsmod': jc.parsers.lsmod.parse,
'--lsof': jc.parsers.lsof.parse,
'--mount': jc.parsers.mount.parse,
'--netstat': jc.parsers.netstat.parse,
'--ps': jc.parsers.ps.parse,
'--route': jc.parsers.route.parse,
'--ss': jc.parsers.ss.parse,
'--stat': jc.parsers.stat.parse,
'--systemctl': jc.parsers.systemctl.parse,
'--systemctl-lj': jc.parsers.systemctl_lj.parse,
'--systemctl-ls': jc.parsers.systemctl_ls.parse,
'--systemctl-luf': jc.parsers.systemctl_luf.parse,
'--uname': jc.parsers.uname.parse,
'--uptime': jc.parsers.uptime.parse,
'--w': jc.parsers.w.parse
}
found = False
if debug:
for arg in sys.argv:
if arg in parser_map:
result = parser_map[arg](data, raw=raw, quiet=quiet)
parser_name = parser_shortname(arg)
if parser_name in parsers:
# load parser module just in time so we don't need to load all modules
parser = parser_module(arg)
result = parser.parse(data, raw=raw, quiet=quiet)
found = True
break
else:
for arg in sys.argv:
if arg in parser_map:
parser_name = parser_shortname(arg)
if parser_name in parsers:
# load parser module just in time so we don't need to load all modules
parser = parser_module(arg)
try:
result = parser_map[arg](data, raw=raw, quiet=quiet)
result = parser.parse(data, raw=raw, quiet=quiet)
found = True
break
except:
parser_name = arg.lstrip('--')
jc.utils.error_message(f'{parser_name} parser could not parse the input data. Did you use the correct parser?\n For details use the -d option.')
exit(1)
except Exception:
jc.utils.error_message(
f'{parser_name} parser could not parse the input data. Did you use the correct parser?\n For details use the -d option.')
sys.exit(1)
if not found:
helptext('missing or incorrect arguments')
exit()
sys.exit(1)
# output resulting dictionary as json
if pretty:
print(json.dumps(result, indent=2))
else:
print(json.dumps(result))
json_out(result, pretty=pretty)
if __name__ == '__main__':

141
jc/parsers/airport.py Normal file
View File

@@ -0,0 +1,141 @@
"""jc - JSON CLI output utility airport -I Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -I (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -I | jc --airport -p
{
"agrctlrssi": -66,
"agrextrssi": 0,
"agrctlnoise": -90,
"agrextnoise": 0,
"state": "running",
"op_mode": "station",
"lasttxrate": 195,
"maxrate": 867,
"lastassocstatus": 0,
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": 0,
"channel": "48,80"
}
$ airport -I | jc --airport -p -r
{
"agrctlrssi": "-66",
"agrextrssi": "0",
"agrctlnoise": "-90",
"agrextnoise": "0",
"state": "running",
"op_mode": "station",
"lasttxrate": "195",
"maxrate": "867",
"lastassocstatus": "0",
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": "0",
"channel": "48,80"
}
"""
import jc.utils
class info():
version = '1.0'
description = 'airport -I command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['darwin']
magic_commands = ['airport -I']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"agrctlrssi": integer,
"agrextrssi": integer,
"agrctlnoise": integer,
"agrextnoise": integer,
"state": string,
"op_mode": string,
"lasttxrate": integer,
"maxrate": integer,
"lastassocstatus": integer,
"802_11_auth": string,
"link_auth": string,
"bssid": string,
"ssid": string,
"mcs": integer,
"channel": string
}
"""
# integer changes
int_list = ['agrctlrssi', 'agrextrssi', 'agrctlnoise', 'agrextnoise',
'lasttxrate', 'maxrate', 'lastassocstatus', 'mcs']
for key in proc_data:
if key in int_list:
try:
proc_data[key] = int(proc_data[key])
except (ValueError):
proc_data[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
for line in filter(None, data.splitlines()):
linedata = line.split(':', maxsplit=1)
raw_output[linedata[0].strip().lower().replace(' ', '_').replace('.', '_')] = linedata[1].strip()
if raw:
return raw_output
else:
return process(raw_output)

186
jc/parsers/airport_s.py Normal file
View File

@@ -0,0 +1,186 @@
"""jc - JSON CLI output utility airport -s Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -s (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -s | jc --airport-s -p
[
{
"ssid": "DIRECT-4A-HP OfficeJet 3830",
"bssid": "00:67:eb:2a:a7:3b",
"rssi": -90,
"channel": "6",
"ht": true,
"cc": "--",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "Latitude38",
"bssid": "c0:ff:d5:d2:7a:f3",
"rssi": -85,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "xfinitywifi",
"bssid": "6e:e3:0e:b8:45:99",
"rssi": -83,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"NONE"
]
},
...
]
$ airport -s | jc --airport -p -r
[
{
"ssid": "DIRECT-F3-HP ENVY 5660 series",
"bssid": "b0:5a:da:6f:0a:d4",
"rssi": "-93",
"channel": "1",
"ht": "Y",
"cc": "--",
"security": "WPA2(PSK/AES/AES)"
},
{
"ssid": "YouAreInfected-5",
"bssid": "5c:e3:0e:c2:85:da",
"rssi": "-85",
"channel": "36",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
{
"ssid": "YuanFamily",
"bssid": "5c:e3:0e:b8:5f:9a",
"rssi": "-84",
"channel": "11",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
...
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'airport -s command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['darwin']
magic_commands = ['airport -s']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"ssid": string,
"bssid": string,
"rssi": integer,
"channel": string,
"ht": boolean,
"cc": string,
"security": [
string,
]
}
]
"""
for entry in proc_data:
# integers
int_list = ['rssi']
for key in int_list:
if key in entry:
try:
entry[key] = int(entry[key])
except (ValueError):
entry[key] = None
# booleans
bool_list = ['ht']
for key in entry:
if key in bool_list:
try:
entry[key] = True if entry[key] == 'Y' else False
except (ValueError):
entry[key] = None
if 'security' in entry:
entry['security'] = entry['security'].split()
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
# fix headers
cleandata[0] = cleandata[0].lower()
cleandata[0] = cleandata[0].replace('-', '_')
cleandata[0] = cleandata[0].replace('security (auth/unicast/group)', 'security')
# parse the data
raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,7 +1,16 @@
"""jc - JSON CLI output utility arp Parser
Usage:
specify --arp as the first argument if the piped input is coming from arp
specify --arp as the first argument if the piped input is coming from:
arp
or
arp -a
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
@@ -78,6 +87,21 @@ Examples:
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.1'
description = 'arp command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['arp']
__version__ = info.version
def process(proc_data):
@@ -90,7 +114,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -124,49 +148,61 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
# code adapted from Conor Heine at:
# https://gist.github.com/cahna/43a1a3ff4d075bcd71f9d7120037a501
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
# remove final Entries row if -v was used
if cleandata[-1].find("Entries:") == 0:
if cleandata[-1].find('Entries:') == 0:
cleandata.pop(-1)
# detect if linux or bsd style was used
if cleandata[0].find('Address') == 0:
# fix header row to change Flags Mask to flags_mask
cleandata[0] = cleandata[0].replace('Flags Mask', 'flags_mask')
headers = [h for h in ' '.join(cleandata[0].lower().strip().split()).split() if h]
raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:])
raw_output = [dict(zip(headers, r)) for r in raw_data]
if raw:
return raw_output
else:
return process(raw_output)
else:
# detect if osx style was used
if cleandata[0].find(' ifscope ') != -1:
raw_output = []
for line in cleandata:
line = line.split()
output_line = {}
output_line['name'] = line[0]
output_line['address'] = line[1].lstrip('(').rstrip(')')
output_line['hwtype'] = line[4].lstrip('[').rstrip(']')
output_line['hwtype'] = line[-1].lstrip('[').rstrip(']')
output_line['hwaddress'] = line[3]
output_line['iface'] = line[6]
output_line['iface'] = line[5]
raw_output.append(output_line)
if raw:
return raw_output
else:
return process(raw_output)
# detect if linux style was used
elif cleandata[0].find('Address') == 0:
# fix header row to change Flags Mask to flags_mask
cleandata[0] = cleandata[0].replace('Flags Mask', 'flags_mask')
cleandata[0] = cleandata[0].lower()
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
if raw:
return raw_output
else:
return process(raw_output)
# otherwise, try bsd style
else:
raw_output = []
for line in cleandata:
line = line.split()
output_line = {
'name': line[0],
'address': line[1].lstrip('(').rstrip(')'),
'hwtype': line[4].lstrip('[').rstrip(']'),
'hwaddress': line[3],
'iface': line[6],
}
raw_output.append(output_line)
if raw:

218
jc/parsers/blkid.py Normal file
View File

@@ -0,0 +1,218 @@
"""jc - JSON CLI output utility blkid Parser
Usage:
specify --blkid as the first argument if the piped input is coming from blkid
Compatibility:
'linux'
Examples:
$ blkid | jc --blkid -p
[
{
"device": "/dev/sda1",
"uuid": "05d927ab-5875-49e4-ada1-7f46cb32c932",
"type": "xfs"
},
{
"device": "/dev/sda2",
"uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
"type": "LVM2_member"
},
{
"device": "/dev/mapper/centos-root",
"uuid": "07d718ff-950c-4e5b-98f0-42a1147c77d9",
"type": "xfs"
},
{
"device": "/dev/mapper/centos-swap",
"uuid": "615eb89a-bcbf-46fd-80e3-c483ff5c931f",
"type": "swap"
}
]
$ sudo blkid -o udev -ip /dev/sda2 | jc --blkid -p
[
{
"id_fs_uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
"id_fs_uuid_enc": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
"id_fs_version": "LVM2\\x20001",
"id_fs_type": "LVM2_member",
"id_fs_usage": "raid",
"id_iolimit_minimum_io_size": 512,
"id_iolimit_physical_sector_size": 512,
"id_iolimit_logical_sector_size": 512,
"id_part_entry_scheme": "dos",
"id_part_entry_type": "0x8e",
"id_part_entry_number": 2,
"id_part_entry_offset": 2099200,
"id_part_entry_size": 39843840,
"id_part_entry_disk": "8:0"
}
]
$ sudo blkid -ip /dev/sda1 | jc --blkid -p -r
[
{
"devname": "/dev/sda1",
"uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932",
"type": "xfs",
"usage": "filesystem",
"minimum_io_size": "512",
"physical_sector_size": "512",
"logical_sector_size": "512",
"part_entry_scheme": "dos",
"part_entry_type": "0x83",
"part_entry_flags": "0x80",
"part_entry_number": "1",
"part_entry_offset": "2048",
"part_entry_size": "2097152",
"part_entry_disk": "8:0"
}
]
"""
import shlex
import jc.utils
class info():
version = '1.0'
description = 'blkid command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['blkid']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"device": string,
"uuid": string,
"type": string,
"usage": string,
"part_entry_scheme": string,
"part_entry_type": string,
"part_entry_flags": string,
"part_entry_number": integer,
"part_entry_offset": integer,
"part_entry_size": integer,
"part_entry_disk": string,
"id_fs_uuid": string,
"id_fs_uuid_enc": string,
"id_fs_version": string,
"id_fs_type": string,
"id_fs_usage": string,
"id_part_entry_scheme": string,
"id_part_entry_type": string,
"id_part_entry_flags": string,
"id_part_entry_number": integer,
"id_part_entry_offset": integer,
"id_part_entry_size": integer,
"id_iolimit_minimum_io_size": integer,
"id_iolimit_physical_sector_size": integer,
"id_iolimit_logical_sector_size": integer,
"id_part_entry_disk": string,
"minimum_io_size": integer,
"physical_sector_size": integer,
"logical_sector_size": integer
}
]
"""
for entry in proc_data:
if 'devname' in entry:
entry['device'] = entry.pop('devname')
int_list = ['part_entry_number', 'part_entry_offset', 'part_entry_size', 'id_part_entry_number',
'id_part_entry_offset', 'id_part_entry_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']
for key in int_list:
if key in entry:
try:
entry[key] = int(entry[key])
except (ValueError):
entry[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
if data:
# if the first field is a device, use normal parsing:
if data.split(maxsplit=1)[0][-1] == ':':
linedata = data.splitlines()
for line in linedata:
output_line = {}
entries = shlex.split(line)
output_line['device'] = entries.pop(0)[:-1]
for entry in entries:
key = entry.split('=', maxsplit=1)[0].lower()
value = entry.split('=', maxsplit=1)[1]
output_line[key] = value
raw_output.append(output_line)
# else use key/value per line parsing
else:
linedata = data.splitlines()
output_line = {}
for line in linedata:
if line == '':
if output_line:
raw_output.append(output_line)
output_line = {}
continue
continue
key = line.split('=', maxsplit=1)[0].lower()
value = line.split('=', maxsplit=1)[1]
output_line[key] = value
if output_line:
raw_output.append(output_line)
if raw:
return raw_output
else:
return process(raw_output)

270
jc/parsers/crontab.py Normal file
View File

@@ -0,0 +1,270 @@
"""jc - JSON CLI output utility crontab command and file Parser
Usage:
specify --crontab as the first argument if the piped input is coming from crontab -l or a crontab file
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ crontab -l | jc --crontab -p
{
"variables": [
{
"name": "MAILTO",
"value": "root"
},
{
"name": "PATH",
"value": "/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/bash"
}
],
"schedule": [
{
"minute": [
"5"
],
"hour": [
"10-11",
"22"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"command": "/var/www/devdaily.com/bin/mk-new-links.php"
},
{
"minute": [
"30"
],
"hour": [
"4/2"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"command": "/var/www/devdaily.com/bin/create-all-backups.sh"
},
{
"occurrence": "yearly",
"command": "/home/maverick/bin/annual-maintenance"
},
{
"occurrence": "reboot",
"command": "/home/cleanup"
},
{
"occurrence": "monthly",
"command": "/home/maverick/bin/tape-backup"
}
]
}
$ cat /etc/crontab | jc --crontab -p -r
{
"variables": [
{
"name": "MAILTO",
"value": "root"
},
{
"name": "PATH",
"value": "/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/bash"
}
],
"schedule": [
{
"minute": "5",
"hour": "10-11,22",
"day_of_month": "*",
"month": "*",
"day_of_week": "*",
"command": "/var/www/devdaily.com/bin/mk-new-links.php"
},
{
"minute": "30",
"hour": "4/2",
"day_of_month": "*",
"month": "*",
"day_of_week": "*",
"command": "/var/www/devdaily.com/bin/create-all-backups.sh"
},
{
"occurrence": "yearly",
"command": "/home/maverick/bin/annual-maintenance"
},
{
"occurrence": "reboot",
"command": "/home/cleanup"
},
{
"occurrence": "monthly",
"command": "/home/maverick/bin/tape-backup"
}
]
}
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.1'
description = 'crontab command and file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['crontab']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"variables": [
"name": string,
"value": string
],
"schedule": [
{
"occurrence" string,
"minute": [
string
],
"hour": [
string
],
"day_of_month": [
string
],
"month": [
string
],
"day_of_week": [
string
],
"occurrence": string,
"command": string
}
]
}
"""
# put itmes in lists
try:
for entry in proc_data['schedule']:
entry['minute'] = entry['minute'].split(',')
entry['hour'] = entry['hour'].split(',')
entry['day_of_month'] = entry['day_of_month'].split(',')
entry['month'] = entry['month'].split(',')
entry['day_of_week'] = entry['day_of_week'].split(',')
except (KeyError):
pass
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
# Clear any commented lines
for i, line in reversed(list(enumerate(cleandata))):
if line.strip().find('#') == 0:
cleandata.pop(i)
# Pop any variable assignment lines
cron_var = []
for i, line in reversed(list(enumerate(cleandata))):
if line.find('=') != -1:
var_line = cleandata.pop(i)
var_name = var_line.split('=', maxsplit=1)[0].strip()
var_value = var_line.split('=', maxsplit=1)[1].strip()
cron_var.append({'name': var_name,
'value': var_value})
raw_output['variables'] = cron_var
# Pop any shortcut lines
shortcut_list = []
for i, line in reversed(list(enumerate(cleandata))):
if line.strip().startswith('@'):
shortcut_line = cleandata.pop(i)
occurrence = shortcut_line.split(maxsplit=1)[0].strip().lstrip('@')
cmd = shortcut_line.split(maxsplit=1)[1].strip()
shortcut_list.append({'occurrence': occurrence,
'command': cmd})
# Add header row for parsing
cleandata[:0] = ['minute hour day_of_month month day_of_week command']
if len(cleandata) > 1:
cron_list = jc.parsers.universal.simple_table_parse(cleandata)
raw_output['schedule'] = cron_list
# Add shortcut entries back in
for item in shortcut_list:
raw_output['schedule'].append(item)
if raw:
return raw_output
else:
return process(raw_output)

273
jc/parsers/crontab_u.py Normal file
View File

@@ -0,0 +1,273 @@
"""jc - JSON CLI output utility crontab file Parser
Usage:
specify --crontab-u as the first argument if the piped input is coming from a crontab file with User specified
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ cat /etc/crontab | jc --crontab-u -p
{
"variables": [
{
"name": "PATH",
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/sh"
}
],
"schedule": [
{
"minute": [
"25"
],
"hour": [
"6"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
},
{
"minute": [
"47"
],
"hour": [
"6"
],
"day_of_month": [
"*"
],
"month": [
"*"
],
"day_of_week": [
"7"
],
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
},
{
"minute": [
"52"
],
"hour": [
"6"
],
"day_of_month": [
"1"
],
"month": [
"*"
],
"day_of_week": [
"*"
],
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
}
]
}
$ cat /etc/crontab | jc --crontab-u -p -r
{
"variables": [
{
"name": "PATH",
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
},
{
"name": "SHELL",
"value": "/bin/sh"
}
],
"schedule": [
{
"minute": "25",
"hour": "6",
"day_of_month": "*",
"month": "*",
"day_of_week": "*",
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
},
{
"minute": "47",
"hour": "6",
"day_of_month": "*",
"month": "*",
"day_of_week": "7",
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
},
{
"minute": "52",
"hour": "6",
"day_of_month": "1",
"month": "*",
"day_of_week": "*",
"user": "root",
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
}
]
}
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'crontab file parser with user support'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"variables": [
"name": string,
"value": string
],
"schedule": [
{
"occurrence" string,
"minute": [
string
],
"hour": [
string
],
"day_of_month": [
string
],
"month": [
string
],
"day_of_week": [
string
],
"occurrence": string,
"user": string,
"command": string
}
]
}
"""
# put itmes in lists
try:
for entry in proc_data['schedule']:
entry['minute'] = entry['minute'].split(',')
entry['hour'] = entry['hour'].split(',')
entry['day_of_month'] = entry['day_of_month'].split(',')
entry['month'] = entry['month'].split(',')
entry['day_of_week'] = entry['day_of_week'].split(',')
except (KeyError):
pass
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
# Clear any commented lines
for i, line in reversed(list(enumerate(cleandata))):
if line.strip().find('#') == 0:
cleandata.pop(i)
# Pop any variable assignment lines
cron_var = []
for i, line in reversed(list(enumerate(cleandata))):
if line.find('=') != -1:
var_line = cleandata.pop(i)
var_name = var_line.split('=', maxsplit=1)[0].strip()
var_value = var_line.split('=', maxsplit=1)[1].strip()
cron_var.append({'name': var_name,
'value': var_value})
raw_output['variables'] = cron_var
# Pop any shortcut lines
shortcut_list = []
for i, line in reversed(list(enumerate(cleandata))):
if line.strip().startswith('@'):
shortcut_line = cleandata.pop(i)
occurrence = shortcut_line.split(maxsplit=1)[0].strip().lstrip('@')
usr = shortcut_line.split(maxsplit=2)[1].strip()
cmd = shortcut_line.split(maxsplit=2)[2].strip()
shortcut_list.append({'occurrence': occurrence,
'user': usr,
'command': cmd})
# Add header row for parsing
cleandata[:0] = ['minute hour day_of_month month day_of_week user command']
if len(cleandata) > 1:
cron_list = jc.parsers.universal.simple_table_parse(cleandata)
raw_output['schedule'] = cron_list
# Add shortcut entries back in
for item in shortcut_list:
raw_output['schedule'].append(item)
if raw:
return raw_output
else:
return process(raw_output)

141
jc/parsers/csv.py Normal file
View File

@@ -0,0 +1,141 @@
"""jc - JSON CLI output utility csv Parser
Usage:
specify --csv as the first argument if the piped input is coming from a csv file.
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.
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat homes.csv
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes"
142, 160, 28, 10, 5, 3, 60, 0.28, 3167
175, 180, 18, 8, 4, 1, 12, 0.43, 4033
129, 132, 13, 6, 3, 1, 41, 0.33, 1471
...
$ cat homes.csv | jc --csv -p
[
{
"Sell": "142",
"List": "160",
"Living": "28",
"Rooms": "10",
"Beds": "5",
"Baths": "3",
"Age": "60",
"Acres": "0.28",
"Taxes": "3167"
},
{
"Sell": "175",
"List": "180",
"Living": "18",
"Rooms": "8",
"Beds": "4",
"Baths": "1",
"Age": "12",
"Acres": "0.43",
"Taxes": "4033"
},
{
"Sell": "129",
"List": "132",
"Living": "13",
"Rooms": "6",
"Beds": "3",
"Baths": "1",
"Age": "41",
"Acres": "0.33",
"Taxes": "1471"
},
...
]
"""
import jc.utils
import csv
class info():
version = '1.0'
description = 'CSV file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the python standard csv library'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Each dictionary represents a row in the csv file:
[
{
csv file converted to a Dictionary
https://docs.python.org/3/library/csv.html
}
]
"""
# No further processing
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
dialect = None
try:
dialect = csv.Sniffer().sniff(data[:1024])
except Exception:
pass
reader = csv.DictReader(cleandata, dialect=dialect)
for row in reader:
raw_output.append(row)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,15 +1,20 @@
"""jc - JSON CLI output utility df Parser
Usage:
specify --df as the first argument if the piped input is coming from df
Compatibility:
'linux', 'darwin'
Examples:
$ df | jc --df -p
[
{
"filesystem": "devtmpfs",
"1k-blocks": 1918820,
"1k_blocks": 1918820,
"used": 0,
"available": 1918820,
"use_percent": 0,
@@ -17,7 +22,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": 1930668,
"1k_blocks": 1930668,
"used": 0,
"available": 1930668,
"use_percent": 0,
@@ -25,7 +30,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": 1930668,
"1k_blocks": 1930668,
"used": 11800,
"available": 1918868,
"use_percent": 1,
@@ -38,7 +43,7 @@ Examples:
[
{
"filesystem": "devtmpfs",
"1k-blocks": "1918820",
"1k_blocks": "1918820",
"used": "0",
"available": "1918820",
"use_percent": "0%",
@@ -46,7 +51,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": "1930668",
"1k_blocks": "1930668",
"used": "0",
"available": "1930668",
"use_percent": "0%",
@@ -54,7 +59,7 @@ Examples:
},
{
"filesystem": "tmpfs",
"1k-blocks": "1930668",
"1k_blocks": "1930668",
"used": "11800",
"available": "1918868",
"use_percent": "1%",
@@ -64,6 +69,21 @@ Examples:
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.1'
description = 'df command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin']
magic_commands = ['df']
__version__ = info.version
def process(proc_data):
@@ -76,36 +96,64 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"filesystem": string,
"size": string,
"1k-blocks": integer,
"used": integer,
"available": integer,
"use_percent": integer,
"mounted_on": string
"filesystem": string,
"size": string,
"1k_blocks": integer,
"512_blocks": integer,
"used": integer,
"available": integer,
"capacity_percent": integer,
"ifree": integer,
"iused": integer,
"use_percent": integer,
"iused_percent": integer,
"mounted_on": string
}
]
"""
for entry in proc_data:
# change any entry for key with '-blocks' in the name to int
# change 'avail' to 'available'
if 'avail' in entry:
entry['available'] = entry.pop('avail')
# change 'use%' to 'use_percent'
if 'use%' in entry:
entry['use_percent'] = entry.pop('use%')
# change 'capacity' to 'capacity_percent'
if 'capacity' in entry:
entry['capacity_percent'] = entry.pop('capacity')
# change '%iused' to 'iused_percent'
if '%iused' in entry:
entry['iused_percent'] = entry.pop('%iused')
# change any entry for key with '_blocks' in the name to int
for k in entry:
if str(k).find('-blocks') != -1:
if str(k).find('_blocks') != -1:
try:
blocks_int = int(entry[k])
entry[k] = blocks_int
except (ValueError):
entry[k] = None
# remove percent sign from 'use_percent'
# remove percent sign from 'use_percent', 'capacity_percent', and 'iused_percent'
if 'use_percent' in entry:
entry['use_percent'] = entry['use_percent'].rstrip('%')
# change used, available, and use_percent to int
int_list = ['used', 'available', 'use_percent']
if 'capacity_percent' in entry:
entry['capacity_percent'] = entry['capacity_percent'].rstrip('%')
if 'iused_percent' in entry:
entry['iused_percent'] = entry['iused_percent'].rstrip('%')
# 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']
for key in int_list:
if key in entry:
try:
@@ -129,23 +177,21 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
fix_headers = cleandata[0].lower().replace('avail ', 'available ')
fix_headers = fix_headers.replace('use%', 'use_percent')
fix_headers = fix_headers.replace('mounted on', 'mounted_on')
headers = [h for h in ' '.join(fix_headers.strip().split()).split() if h]
raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:])
raw_output = [dict(zip(headers, r)) for r in raw_data]
# fix headers
cleandata[0] = cleandata[0].lower()
cleandata[0] = cleandata[0].replace('-', '_')
cleandata[0] = cleandata[0].replace('mounted on', 'mounted_on')
# parse the data
raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
if raw:
return raw_output

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility dig Parser
Usage:
Specify --dig as the first argument if the piped input is coming from dig
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p
@@ -318,6 +323,20 @@ Examples:
import jc.utils
class info():
version = '1.0'
description = 'dig command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['dig']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -328,7 +347,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -501,14 +520,11 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()

152
jc/parsers/du.py Normal file
View File

@@ -0,0 +1,152 @@
"""jc - JSON CLI output utility du Parser
Usage:
specify --du as the first argument if the piped input is coming from du
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ du /usr | jc --du -p
[
{
"size": 104608,
"name": "/usr/bin"
},
{
"size": 56,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature"
},
{
"size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone"
},
{
"size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local"
},
{
"size": 0,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr"
},
{
"size": 1008,
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu"
},
...
]
$ du /usr | jc --du -p -r
[
{
"size": "104608",
"name": "/usr/bin"
},
{
"size": "56",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/_CodeSignature"
},
{
"size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local/standalone"
},
{
"size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr/local"
},
{
"size": "0",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/usr"
},
{
"size": "1008",
"name": "/usr/standalone/firmware/iBridge1_1Customer.bundle/Contents/Resources/Firmware/dfu"
},
...
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.1'
description = 'du command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['du']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"size": integer,
"name": string
}
]
"""
int_list = ['size']
for entry in proc_data:
for key in int_list:
if key in entry:
try:
key_int = int(entry[key])
entry[key] = key_int
except (ValueError):
entry[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
cleandata.insert(0, 'size name')
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility env Parser
Usage:
specify --env as the first argument if the piped input is coming from env
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ env | jc --env -p
@@ -46,6 +51,20 @@ Examples:
import jc.utils
class info():
version = '1.1'
description = 'env command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['env']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -56,7 +75,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -89,14 +108,11 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
Dictionary of raw structured data or
list of dictionaries of processed structured data
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}

128
jc/parsers/file.py Normal file
View File

@@ -0,0 +1,128 @@
"""jc - JSON CLI output utility file command Parser
Usage:
specify --file as the first argument if the piped input is coming from file.
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
$ file * | jc --file -p
[
{
"filename": "Applications",
"type": "directory"
},
{
"filename": "another file with spaces",
"type": "empty"
},
{
"filename": "argstest.py",
"type": "Python script text executable, ASCII text"
},
{
"filename": "blkid-p.out",
"type": "ASCII text"
},
{
"filename": "blkid-pi.out",
"type": "ASCII text, with very long lines"
},
{
"filename": "cd_catalog.xml",
"type": "XML 1.0 document text, ASCII text, with CRLF line terminators"
},
{
"filename": "centosserial.sh",
"type": "Bourne-Again shell script text executable, UTF-8 Unicode text"
},
...
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'file command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['file']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"filename": string,
"type ": string
}
]
"""
# No further processing
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
warned = False
for line in filter(None, data.splitlines()):
linedata = line.rsplit(':', maxsplit=1)
try:
filename = linedata[0].strip()
filetype = linedata[1].strip()
raw_output.append(
{
'filename': filename,
'type': filetype
}
)
except IndexError:
if not warned:
jc.utils.warning_message('Filenames with newline characters detected. Some filenames may be truncated.')
warned = True
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility foo Parser
Usage:
specify --foo as the first argument if the piped input is coming from foo
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ foo | jc --foo -p
@@ -14,6 +19,21 @@ Examples:
import jc.utils
class info():
version = '1.0'
description = 'foo command parser'
author = 'John Doe'
author_email = 'johndoe@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['foo']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -24,7 +44,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -51,22 +71,14 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
for line in filter(None, data.splitlines()):
# parse the content
pass

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility free Parser
Usage:
specify --free as the first argument if the piped input is coming from free
Compatibility:
'linux'
Examples:
$ free | jc --free -p
@@ -44,6 +49,21 @@ Examples:
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'free command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['free']
__version__ = info.version
def process(proc_data):
@@ -56,7 +76,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -96,28 +116,17 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
# code adapted from Conor Heine at:
# https://gist.github.com/cahna/43a1a3ff4d075bcd71f9d7120037a501
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
headers = [h for h in ' '.join(cleandata[0].lower().strip().split()).split() if h]
headers.insert(0, "type")
cleandata[0] = cleandata[0].lower()
cleandata[0] = cleandata[0].replace('buff/cache', 'buff_cache')
cleandata[0] = 'type ' + cleandata[0]
# clean up 'buff/cache' header
# even though forward slash in a key is valid json, it can make things difficult
headers = ['buff_cache' if x == 'buff/cache' else x for x in headers]
raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:])
raw_output = [dict(zip(headers, r)) for r in raw_data]
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
for entry in raw_output:
entry['type'] = entry['type'].rstrip(':')

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility fstab Parser
Usage:
specify --fstab as the first argument if the piped input is coming from a fstab file
Compatibility:
'linux'
Examples:
$ cat /etc/fstab | jc --fstab -p
@@ -64,6 +69,19 @@ Examples:
import jc.utils
class info():
version = '1.0'
description = 'fstab file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -74,7 +92,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -112,14 +130,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()

190
jc/parsers/group.py Normal file
View File

@@ -0,0 +1,190 @@
"""jc - JSON CLI output utility /etc/group file Parser
Usage:
specify --group as the first argument if the piped input is coming from /etc/group
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ cat /etc/group | jc --group -p
[
{
"group_name": "nobody",
"password": "*",
"gid": -2,
"members": []
},
{
"group_name": "nogroup",
"password": "*",
"gid": -1,
"members": []
},
{
"group_name": "wheel",
"password": "*",
"gid": 0,
"members": [
"root"
]
},
{
"group_name": "certusers",
"password": "*",
"gid": 29,
"members": [
"root",
"_jabber",
"_postfix",
"_cyrus",
"_calendar",
"_dovecot"
]
},
...
]
$ cat /etc/group | jc --group -p -r
[
{
"group_name": "nobody",
"password": "*",
"gid": "-2",
"members": [
""
]
},
{
"group_name": "nogroup",
"password": "*",
"gid": "-1",
"members": [
""
]
},
{
"group_name": "wheel",
"password": "*",
"gid": "0",
"members": [
"root"
]
},
{
"group_name": "certusers",
"password": "*",
"gid": "29",
"members": [
"root",
"_jabber",
"_postfix",
"_cyrus",
"_calendar",
"_dovecot"
]
},
...
]
"""
import jc.utils
class info():
version = '1.0'
description = '/etc/group file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"group_name": string,
"password": string,
"gid": integer,
"members": [
string
]
}
]
"""
for entry in proc_data:
int_list = ['gid']
for key in int_list:
if key in entry:
try:
key_int = int(entry[key])
entry[key] = key_int
except (ValueError):
entry[key] = None
if entry['members'] == ['']:
entry['members'] = []
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
for entry in cleandata:
if entry.startswith('#'):
continue
output_line = {}
fields = entry.split(':')
output_line['group_name'] = fields[0]
output_line['password'] = fields[1]
output_line['gid'] = fields[2]
output_line['members'] = fields[3].split(',')
raw_output.append(output_line)
if raw:
return raw_output
else:
return process(raw_output)

152
jc/parsers/gshadow.py Normal file
View File

@@ -0,0 +1,152 @@
"""jc - JSON CLI output utility /etc/gshadow file Parser
Usage:
specify --gshadow as the first argument if the piped input is coming from /etc/gshadow
Compatibility:
'linux', 'aix', 'freebsd'
Examples:
$ cat /etc/gshadow | jc --gshadow -p
[
{
"group_name": "root",
"password": "*",
"administrators": [],
"members": []
},
{
"group_name": "adm",
"password": "*",
"administrators": [],
"members": [
"syslog",
"joeuser"
]
},
...
]
$ cat /etc/gshadow | jc --gshadow -p -r
[
{
"group_name": "root",
"password": "*",
"administrators": [
""
],
"members": [
""
]
},
{
"group_name": "adm",
"password": "*",
"administrators": [
""
],
"members": [
"syslog",
"joeuser"
]
},
...
]
"""
import jc.utils
class info():
version = '1.0'
description = '/etc/gshadow file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"group_name": string,
"password": string,
"administrators": [
string
],
"members": [
string
]
}
]
"""
for entry in proc_data:
if entry['administrators'] == ['']:
entry['administrators'] = []
if entry['members'] == ['']:
entry['members'] = []
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
for entry in cleandata:
if entry.startswith('#'):
continue
output_line = {}
fields = entry.split(':')
output_line['group_name'] = fields[0]
output_line['password'] = fields[1]
output_line['administrators'] = fields[2].split(',')
output_line['members'] = fields[3].split(',')
raw_output.append(output_line)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,26 +1,31 @@
"""jc - JSON CLI output utility history Parser
Usage:
specify --history as the first argument if the piped input is coming from history
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
$ history | jc --history -p
[
{
"line": "118",
"line": 118,
"command": "sleep 100"
},
{
"line": "119",
"line": 119,
"command": "ls /bin"
},
{
"line": "120",
"line": 120,
"command": "echo \"hello\""
},
{
"line": "121",
"line": 121,
"command": "docker images"
},
...
@@ -35,7 +40,21 @@ Examples:
...
}
"""
import jc
import jc.utils
class info():
version = '1.2'
description = 'history command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Optimizations by https://github.com/philippeitis'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
@@ -48,11 +67,11 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"line": string,
"line": integer,
"command": string
}
]
@@ -61,11 +80,11 @@ def process(proc_data):
# rebuild output for added semantic information
processed = []
for k, v in proc_data.items():
proc_line = {}
proc_line['line'] = k
proc_line['command'] = v
proc_line = {
'line': int(k) if k.isdigit() else None,
'command': v,
}
processed.append(proc_line)
return processed
@@ -81,31 +100,25 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
Dictionary of raw structured data or
list of dictionaries of processed structured data
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
# split lines and clear out any non-ascii chars
linedata = data.encode('ascii', errors='ignore').decode().splitlines()
# Clear any blank lines
cleandata = list(filter(None, linedata))
if cleandata:
for entry in cleandata:
try:
parsed_line = entry.split(maxsplit=1)
raw_output[parsed_line[0]] = parsed_line[1]
except IndexError:
# need to catch indexerror in case there is weird input from prior commands
pass
# Skip any blank lines
for entry in filter(None, linedata):
try:
parsed_line = entry.split(maxsplit=1)
raw_output[parsed_line[0]] = parsed_line[1]
except IndexError:
# need to catch indexerror in case there is weird input from prior commands
pass
if raw:
return raw_output

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility hosts Parser
Usage:
specify --hosts as the first argument if the piped input is coming from a hosts file
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat /etc/hosts | jc --hosts -p
@@ -55,6 +60,19 @@ Examples:
import jc.utils
class info():
version = '1.0'
description = '/etc/hosts file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -65,7 +83,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -93,14 +111,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()

215
jc/parsers/id.py Normal file
View File

@@ -0,0 +1,215 @@
"""jc - JSON CLI output utility id Parser
Usage:
specify --id as the first argument if the piped input is coming from id
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ id | jc --id -p
{
"uid": {
"id": 1000,
"name": "joeuser"
},
"gid": {
"id": 1000,
"name": "joeuser"
},
"groups": [
{
"id": 1000,
"name": "joeuser"
},
{
"id": 10,
"name": "wheel"
}
],
"context": {
"user": "unconfined_u",
"role": "unconfined_r",
"type": "unconfined_t",
"level": "s0-s0:c0.c1023"
}
}
$ id | jc --id -p -r
{
"uid": {
"id": "1000",
"name": "joeuser"
},
"gid": {
"id": "1000",
"name": "joeuser"
},
"groups": [
{
"id": "1000",
"name": "joeuser"
},
{
"id": "10",
"name": "wheel"
}
],
"context": {
"user": "unconfined_u",
"role": "unconfined_r",
"type": "unconfined_t",
"level": "s0-s0:c0.c1023"
}
}
"""
import jc.utils
class info():
version = '1.0'
description = 'id command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['id']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"uid": {
"id": integer,
"name": string
},
"gid": {
"id": integer,
"name": string
},
"groups": [
{
"id": integer,
"name": string
},
{
"id": integer,
"name": string
}
],
"context": {
"user": string,
"role": string,
"type": string,
"level": string
}
}
"""
if 'uid' in proc_data:
if 'id' in proc_data['uid']:
try:
proc_data['uid']['id'] = int(proc_data['uid']['id'])
except (ValueError):
proc_data['uid']['id'] = None
if 'gid' in proc_data:
if 'id' in proc_data['gid']:
try:
proc_data['gid']['id'] = int(proc_data['gid']['id'])
except (ValueError):
proc_data['gid']['id'] = None
if 'groups' in proc_data:
for group in proc_data['groups']:
if 'id' in group:
try:
group['id'] = int(group['id'])
except (ValueError):
group['id'] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
cleandata = data.split()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
for section in cleandata:
if section.startswith('uid'):
uid_parsed = section.replace('(', '=').replace(')', '=')
uid_parsed = uid_parsed.split('=')
raw_output['uid'] = {}
raw_output['uid']['id'] = uid_parsed[1]
raw_output['uid']['name'] = uid_parsed[2]
if section.startswith('gid'):
gid_parsed = section.replace('(', '=').replace(')', '=')
gid_parsed = gid_parsed.split('=')
raw_output['gid'] = {}
raw_output['gid']['id'] = gid_parsed[1]
raw_output['gid']['name'] = gid_parsed[2]
if section.startswith('groups'):
groups_parsed = section.replace('(', '=').replace(')', '=')
groups_parsed = groups_parsed.replace('groups=', '')
groups_parsed = groups_parsed.split(',')
raw_output['groups'] = []
for group in groups_parsed:
group_dict = {}
grp_parsed = group.split('=')
group_dict['id'] = grp_parsed[0]
group_dict['name'] = grp_parsed[1]
raw_output['groups'].append(group_dict)
if section.startswith('context'):
context_parsed = section.replace('context=', '')
context_parsed = context_parsed.split(':', maxsplit=3)
raw_output['context'] = {}
raw_output['context']['user'] = context_parsed[0]
raw_output['context']['role'] = context_parsed[1]
raw_output['context']['type'] = context_parsed[2]
raw_output['context']['level'] = context_parsed[3]
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,10 +1,15 @@
"""jc - JSON CLI output utility ifconfig Parser
Usage:
specify --ifconfig as the first argument if the piped input is coming from ifconfig
no ifconfig options are supported.
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
$ ifconfig | jc --ifconfig -p
@@ -12,22 +17,29 @@ Examples:
{
"name": "ens33",
"flags": 4163,
"state": "UP,BROADCAST,RUNNING,MULTICAST",
"state": [
"UP",
"BROADCAST",
"RUNNING",
"MULTICAST"
],
"mtu": 1500,
"ipv4_addr": "192.168.71.138",
"ipv4_addr": "192.168.71.137",
"ipv4_mask": "255.255.255.0",
"ipv4_bcast": "192.168.71.255",
"ipv6_addr": "fe80::c1cb:715d:bc3e:b8a0",
"ipv6_mask": 64,
"ipv6_scope": "link",
"ipv6_scope": "0x20",
"mac_addr": "00:0c:29:3b:58:0e",
"type": "Ethernet",
"rx_packets": 6374,
"rx_packets": 8061,
"rx_bytes": 1514413,
"rx_errors": 0,
"rx_dropped": 0,
"rx_overruns": 0,
"rx_frame": 0,
"tx_packets": 3707,
"tx_packets": 4502,
"tx_bytes": 866622,
"tx_errors": 0,
"tx_dropped": 0,
"tx_overruns": 0,
@@ -38,22 +50,28 @@ Examples:
{
"name": "lo",
"flags": 73,
"state": "UP,LOOPBACK,RUNNING",
"state": [
"UP",
"LOOPBACK",
"RUNNING"
],
"mtu": 65536,
"ipv4_addr": "127.0.0.1",
"ipv4_mask": "255.0.0.0",
"ipv4_bcast": null,
"ipv6_addr": "::1",
"ipv6_mask": 128,
"ipv6_scope": "host",
"ipv6_scope": "0x10",
"mac_addr": null,
"type": "Local Loopback",
"rx_packets": 81,
"rx_packets": 73,
"rx_bytes": 6009,
"rx_errors": 0,
"rx_dropped": 0,
"rx_overruns": 0,
"rx_frame": 0,
"tx_packets": 81,
"tx_packets": 73,
"tx_bytes": 6009,
"tx_errors": 0,
"tx_dropped": 0,
"tx_overruns": 0,
@@ -70,20 +88,22 @@ Examples:
"flags": "4163",
"state": "UP,BROADCAST,RUNNING,MULTICAST",
"mtu": "1500",
"ipv4_addr": "192.168.71.135",
"ipv4_addr": "192.168.71.137",
"ipv4_mask": "255.255.255.0",
"ipv4_bcast": "192.168.71.255",
"ipv6_addr": "fe80::c1cb:715d:bc3e:b8a0",
"ipv6_mask": "64",
"ipv6_scope": "link",
"ipv6_scope": "0x20",
"mac_addr": "00:0c:29:3b:58:0e",
"type": "Ethernet",
"rx_packets": "26348",
"rx_packets": "8061",
"rx_bytes": "1514413",
"rx_errors": "0",
"rx_dropped": "0",
"rx_overruns": "0",
"rx_frame": "0",
"tx_packets": "5308",
"tx_packets": "4502",
"tx_bytes": "866622",
"tx_errors": "0",
"tx_dropped": "0",
"tx_overruns": "0",
@@ -101,15 +121,17 @@ Examples:
"ipv4_bcast": null,
"ipv6_addr": "::1",
"ipv6_mask": "128",
"ipv6_scope": "host",
"ipv6_scope": "0x10",
"mac_addr": null,
"type": "Local Loopback",
"rx_packets": "64",
"rx_packets": "73",
"rx_bytes": "6009",
"rx_errors": "0",
"rx_dropped": "0",
"rx_overruns": "0",
"rx_frame": "0",
"tx_packets": "64",
"tx_packets": "73",
"tx_bytes": "6009",
"tx_errors": "0",
"tx_dropped": "0",
"tx_overruns": "0",
@@ -123,6 +145,21 @@ import jc.utils
from ifconfigparser import IfconfigParser
class info():
version = '1.5'
description = 'ifconfig command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using ifconfig-parser package from https://github.com/KnightWhoSayNi/ifconfig-parser'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['ifconfig']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -133,13 +170,15 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"name": string,
"flags": integer,
"state": string,
"state": [
string
],
"mtu": integer,
"ipv4_addr": string,
"ipv4_mask": string,
@@ -150,11 +189,13 @@ def process(proc_data):
"mac_addr": string,
"type": string,
"rx_packets": integer,
"rx_bytes": integer,
"rx_errors": integer,
"rx_dropped": integer,
"rx_overruns": integer,
"rx_frame": integer,
"tx_packets": integer,
"tx_bytes": integer,
"tx_errors": integer,
"tx_dropped": integer,
"tx_overruns": integer,
@@ -165,8 +206,8 @@ def process(proc_data):
]
"""
for entry in proc_data:
int_list = ['flags', 'mtu', 'ipv6_mask', 'rx_packets', 'rx_errors', 'rx_dropped', 'rx_overruns',
'rx_frame', 'tx_packets', 'tx_errors', 'tx_dropped', 'tx_overruns', 'tx_carrier',
int_list = ['flags', 'mtu', 'ipv6_mask', 'rx_packets', 'rx_bytes', 'rx_errors', 'rx_dropped', 'rx_overruns',
'rx_frame', 'tx_packets', 'tx_bytes', 'tx_errors', 'tx_dropped', 'tx_overruns', 'tx_carrier',
'tx_collisions', 'metric']
for key in int_list:
if key in entry:
@@ -176,6 +217,25 @@ def process(proc_data):
except (ValueError, TypeError):
entry[key] = None
# convert OSX-style subnet mask to dotted quad
if 'ipv4_mask' in entry:
try:
if entry['ipv4_mask'].find('0x') == 0:
new_mask = entry['ipv4_mask']
new_mask = new_mask.lstrip('0x')
new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)])
entry['ipv4_mask'] = new_mask
except (ValueError, TypeError, AttributeError):
pass
# convert state value to an array
if 'state' in entry:
try:
new_state = entry['state'].split(',')
entry['state'] = new_state
except (ValueError, TypeError, AttributeError):
pass
return proc_data
@@ -184,21 +244,17 @@ def parse(data, raw=False, quiet=False):
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []

112
jc/parsers/ini.py Normal file
View File

@@ -0,0 +1,112 @@
"""jc - JSON CLI output utility INI Parser
Usage:
specify --ini as the first argument if the piped input is coming from an INI file
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ cat example.ini
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
$ cat example.ini | jc --ini -p
{
"bitbucket.org": {
"serveraliveinterval": "45",
"compression": "yes",
"compressionlevel": "9",
"forwardx11": "yes",
"user": "hg"
},
"topsecret.server.com": {
"serveraliveinterval": "45",
"compression": "yes",
"compressionlevel": "9",
"forwardx11": "no",
"port": "50022"
}
}
"""
import jc.utils
import configparser
class info():
version = '1.0'
description = 'INI file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using configparser from the standard library'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary representing an ini document:
{
ini document converted to a dictionary
see configparser standard library documentation for more details
}
"""
# No further processing
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary representing the ini file
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
if data:
ini = configparser.ConfigParser()
ini.read_string(data)
raw_output = {s: dict(ini.items(s)) for s in ini.sections()}
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,10 +1,15 @@
"""jc - JSON CLI output utility ipables Parser
Usage:
Specify --iptables as the first argument if the piped input is coming from iptables
Supports -vLn and --line-numbers for all tables
Compatibility:
'linux'
Examples:
$ sudo iptables --line-numbers -v -L -t nat | jc --iptables -p
@@ -128,6 +133,20 @@ Examples:
import jc.utils
class info():
version = '1.1'
description = 'iptables command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['iptables']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -138,8 +157,8 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"chain": string,
@@ -215,14 +234,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
chain = {}

View File

@@ -1,10 +1,15 @@
"""jc - JSON CLI output utility jobs Parser
Usage:
specify --jobs as the first argument if the piped input is coming from jobs
Also supports the -l option
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Example:
$ jobs -l | jc --jobs -p
@@ -71,6 +76,20 @@ import string
import jc.utils
class info():
version = '1.0'
description = 'jobs command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['jobs']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -81,7 +100,8 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"job_number": integer,
@@ -117,14 +137,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []

181
jc/parsers/last.py Normal file
View File

@@ -0,0 +1,181 @@
"""jc - JSON CLI output utility last Parser
Usage:
specify --last as the first argument if the piped input is coming from last or lastb
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ last | jc --last -p
[
{
"user": "kbrazil",
"tty": "ttys002",
"hostname": null,
"login": "Thu Feb 27 14:31",
"logout": "still logged in"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": null,
"login": "Thu Feb 27 10:38",
"logout": "10:38",
"duration": "00:00"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": null,
"login": "Thu Feb 27 10:18",
"logout": "10:18",
"duration": "00:00"
},
...
]
$ last | jc --last -p -r
[
{
"user": "kbrazil",
"tty": "ttys002",
"hostname": "-",
"login": "Thu Feb 27 14:31",
"logout": "still_logged_in"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": "-",
"login": "Thu Feb 27 10:38",
"logout": "10:38",
"duration": "00:00"
},
{
"user": "kbrazil",
"tty": "ttys003",
"hostname": "-",
"login": "Thu Feb 27 10:18",
"logout": "10:18",
"duration": "00:00"
},
...
]
"""
import re
import jc.utils
class info():
version = '1.0'
description = 'last and lastb command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['last', 'lastb']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"user": string,
"tty": string,
"hostname": string,
"login": string,
"logout": string,
"duration": string
}
]
"""
for entry in proc_data:
if 'tty' in entry and entry['tty'] == '~':
entry['tty'] = None
if 'tty' in entry and entry['tty'] == 'system_boot':
entry['tty'] = 'system boot'
if 'hostname' in entry and entry['hostname'] == '-':
entry['hostname'] = None
if 'logout' in entry and entry['logout'] == 'still_logged_in':
entry['logout'] = 'still logged in'
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
for entry in cleandata:
output_line = {}
if entry.startswith('wtmp begins ') or entry.startswith('btmp begins '):
continue
entry = entry.replace('system boot', 'system_boot')
entry = entry.replace(' still logged in', '- still_logged_in')
linedata = entry.split()
if re.match(r'[MTWFS][ouerha][nedritnu] [JFMASOND][aepuco][nbrynlgptvc]', ' '.join(linedata[2:4])):
linedata.insert(2, '-')
output_line['user'] = linedata[0]
output_line['tty'] = linedata[1]
output_line['hostname'] = linedata[2]
output_line['login'] = ' '.join(linedata[3:7])
if len(linedata) > 8:
output_line['logout'] = linedata[8]
if len(linedata) > 9:
output_line['duration'] = linedata[9].replace('(', '').replace(')', '')
raw_output.append(output_line)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,14 +1,24 @@
"""jc - JSON CLI output utility ls Parser
Note: The -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 -l or -b is not used.
Usage:
specify --ls as the first argument if the piped input is coming from ls
ls options supported:
- None
- la
- h file sizes will be available in text form with -r but larger file sizes
with human readable suffixes will be converted to Null in default view
since the parser attempts to convert this field to an integer.
-lbaR
--time-style=full-iso
-h file sizes will be available in text form with -r but larger file sizes
with human readable suffixes will be converted to Null in default view
since the parser attempts to convert this field to an integer.
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
@@ -138,6 +148,20 @@ import re
import jc.utils
class info():
version = '1.3'
description = 'ls command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['ls']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -148,13 +172,14 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"filename": string,
"flags": string,
"links": integer,
"parent": string,
"owner": string,
"group": string,
"size": integer,
@@ -188,37 +213,69 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
warned = False
parent = ''
next_is_parent = False
new_section = False
linedata = data.splitlines()
# Delete first line if it starts with 'total'
# Delete first line if it starts with 'total 1234'
if linedata:
if linedata[0].find('total') == 0:
if re.match(r'total [0-9]+', linedata[0]):
linedata.pop(0)
# Clear any blank lines
cleandata = list(filter(None, linedata))
# Look for parent line if glob or -R is used
if not re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', linedata[0]) \
and linedata[0].endswith(':'):
parent = linedata.pop(0)[:-1]
# Pop following total line
linedata.pop(0)
if cleandata:
if linedata:
# Check if -l was used to parse extra data
if re.match('^[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', cleandata[0]):
for entry in cleandata:
if re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', linedata[0]):
for entry in linedata:
output_line = {}
parsed_line = entry.split(maxsplit=8)
if not re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', entry) \
and entry.endswith(':'):
parent = entry[:-1]
new_section = True
# fixup to remove trailing \n in previous entry
raw_output[-1]['filename'] = raw_output[-1]['filename'][:-1]
continue
if re.match(r'total [0-9]+', entry):
new_section = False
continue
# fix for OSX - doesn't print 'total xx' line if empty directory
if new_section and entry == '':
new_section = False
continue
# fixup for filenames with newlines
if not new_section \
and not re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', entry):
raw_output[-1]['filename'] = raw_output[-1]['filename'] + '\n' + entry
continue
# split filenames and links
filename_field = parsed_line[8].split(' -> ')
if len(parsed_line) == 9:
filename_field = parsed_line[8].split(' -> ')
else:
# in case of filenames starting with a newline character
filename_field = ['']
# create list of dictionaries
output_line['filename'] = filename_field[0]
@@ -226,6 +283,9 @@ def parse(data, raw=False, quiet=False):
if len(filename_field) > 1:
output_line['link_to'] = filename_field[1]
if parent:
output_line['parent'] = parent
output_line['flags'] = parsed_line[0]
output_line['links'] = parsed_line[1]
output_line['owner'] = parsed_line[2]
@@ -234,9 +294,27 @@ def parse(data, raw=False, quiet=False):
output_line['date'] = ' '.join(parsed_line[5:8])
raw_output.append(output_line)
else:
for entry in cleandata:
for entry in linedata:
output_line = {}
if entry == '':
next_is_parent = True
continue
if next_is_parent and entry.endswith(':'):
parent = entry[:-1]
next_is_parent = False
continue
if not quiet and next_is_parent and not entry.endswith(':') and not warned:
jc.utils.warning_message('Newline characters detected. Filenames probably corrupted. Use ls -l or -b instead.')
warned = True
output_line['filename'] = entry
if parent:
output_line['parent'] = parent
raw_output.append(output_line)
if raw:

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility lsblk Parser
Usage:
specify --lsblk as the first argument if the piped input is coming from lsblk
Compatibility:
'linux'
Examples:
$ lsblk | jc --lsblk -p
@@ -206,8 +211,22 @@ Examples:
...
]
"""
import string
import jc.utils
import jc.parsers.universal
class info():
version = '1.3'
description = 'lsblk command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['lsblk']
__version__ = info.version
def process(proc_data):
@@ -220,7 +239,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -303,82 +322,25 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
# unicode \u2063 = invisible separator and should not be seen in lsblk output
delim = '\u2063'
raw_output = []
linedata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, linedata))
cleandata = data.splitlines()
header_text = cleandata.pop(0).lower()
header_text = header_text.replace(':', '_')
header_text = header_text.replace('-', '_')
header_text = header_text + ' '
cleandata[0] = cleandata[0].lower()
cleandata[0] = cleandata[0].replace(':', '_')
cleandata[0] = cleandata[0].replace('-', '_')
header_list = header_text.split()
raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
# find each column index and end position
header_search = [header_list[0]]
for h in header_list[1:]:
header_search.append(' ' + h + ' ')
header_spec_list = []
for i, column in enumerate(header_list[0:len(header_list) - 1]):
header_spec = {
'name': column,
'end': header_text.find(header_search[i + 1])
}
header_spec_list.append(header_spec)
# parse lines
if cleandata:
for entry in cleandata:
output_line = {}
# insert new separator since data can contain spaces
for col in reversed(header_list):
# find the right header_spec
for h_spec in header_spec_list:
if h_spec['name'] == col:
h_end = h_spec['end']
# check if the location contains whitespace. if not
# then move to the left until a space is found
while h_end > 0 and entry[h_end] not in string.whitespace:
h_end -= 1
# insert custom delimiter
entry = entry[:h_end] + delim + entry[h_end + 1:]
# create the entry list from the new custom delimiter
entry_list = entry.split(delim, maxsplit=len(header_list) - 1)
# clean up leading and trailing spaces in entry
clean_entry_list = []
for col in entry_list:
clean_entry = col.strip().rstrip()
if clean_entry == '':
clean_entry = None
clean_entry_list.append(clean_entry)
output_line = dict(zip(header_list, clean_entry_list))
raw_output.append(output_line)
# clean up non-ascii characters, if any
for entry in raw_output:
entry['name'] = entry['name'].encode('ascii', errors='ignore').decode()
# clean up non-ascii characters, if any
for entry in raw_output:
entry['name'] = entry['name'].encode('ascii', errors='ignore').decode()
if raw:
return raw_output

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility lsmod Parser
Usage:
specify --lsmod as the first argument if the piped input is coming from lsmod
Compatibility:
'linux'
Examples:
$ lsmod | jc --lsmod -p
@@ -98,6 +103,21 @@ Examples:
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.1'
description = 'lsmod command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['lsmod']
__version__ = info.version
def process(proc_data):
@@ -110,7 +130,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -149,23 +169,15 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
# code adapted from Conor Heine at:
# https://gist.github.com/cahna/43a1a3ff4d075bcd71f9d7120037a501
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
headers = [h for h in ' '.join(cleandata[0].lower().strip().split()).split() if h]
cleandata[0] = cleandata[0].lower()
raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:])
raw_output = [dict(zip(headers, r)) for r in raw_data]
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
for mod in raw_output:
if 'by' in mod:

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility lsof Parser
Usage:
specify --lsof as the first argument if the piped input is coming from lsof
Compatibility:
'linux'
Examples:
$ sudo lsof | jc --lsof -p
@@ -87,8 +92,22 @@ Examples:
...
]
"""
import string
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'lsof command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['lsof']
__version__ = info.version
def process(proc_data):
@@ -101,7 +120,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -143,14 +162,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
@@ -160,7 +175,12 @@ def parse(data, raw=False, quiet=False):
cleandata = list(filter(None, linedata))
if cleandata:
cleandata[0] = cleandata[0].lower()
cleandata[0] = cleandata[0].replace('/', '_')
raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
'''
# find column value of last character of each header
header_text = cleandata.pop(0).lower()
@@ -199,6 +219,7 @@ def parse(data, raw=False, quiet=False):
output_line = dict(zip(headers, fixed_line))
raw_output.append(output_line)
'''
if raw:
return raw_output

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility mount Parser
Usage:
specify --mount as the first argument if the piped input is coming from mount
Compatibility:
'linux', 'darwin'
Example:
$ mount | jc --mount -p
@@ -50,6 +55,20 @@ Example:
import jc.utils
class info():
version = '1.1'
description = 'mount command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin']
magic_commands = ['mount']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -60,8 +79,8 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
"filesystem": string,
@@ -77,6 +96,51 @@ def process(proc_data):
return proc_data
def osx_parse(data):
output = []
for entry in data:
output_line = {}
filesystem = entry.split(' on ')
filesystem = filesystem[0]
output_line['filesystem'] = filesystem
mount_point = entry.split(' on ')
mount_point = mount_point[1].split(' (')
mount_point = mount_point[0]
output_line['mount_point'] = mount_point
options = entry.split('(', maxsplit=1)
options = options[1].rstrip(')')
options = options.split(', ')
output_line['options'] = options
output.append(output_line)
return output
def linux_parse(data):
output = []
for entry in data:
output_line = {}
parsed_line = entry.split()
output_line['filesystem'] = parsed_line[0]
output_line['mount_point'] = parsed_line[2]
output_line['type'] = parsed_line[4]
options = parsed_line[5].lstrip('(').rstrip(')').split(',')
output_line['options'] = options
output.append(output_line)
return output
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
@@ -89,16 +153,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
raw_output = []
jc.utils.compatibility(__name__, info.compatible)
linedata = data.splitlines()
@@ -106,19 +164,12 @@ def parse(data, raw=False, quiet=False):
cleandata = list(filter(None, linedata))
if cleandata:
for entry in cleandata:
output_line = {}
parsed_line = entry.split()
# check for OSX output
if cleandata[0].find(' type ') == -1:
raw_output = osx_parse(cleandata)
output_line['filesystem'] = parsed_line[0]
output_line['mount_point'] = parsed_line[2]
output_line['type'] = parsed_line[4]
access = parsed_line[5].lstrip('(').rstrip(')').split(',')
output_line['options'] = access
raw_output.append(output_line)
else:
raw_output = linux_parse(cleandata)
if raw:
return raw_output

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility netstat Parser
Usage:
Specify --netstat as the first argument if the piped input is coming from netstat
Compatibility:
'linux'
Examples:
$ sudo netstat -apee | jc --netstat -p
@@ -307,6 +312,20 @@ import string
import jc.utils
class info():
version = '1.2'
description = 'netstat command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['netstat']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -317,7 +336,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -506,14 +525,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
cleandata = list(filter(None, cleandata))

297
jc/parsers/ntpq.py Normal file
View File

@@ -0,0 +1,297 @@
"""jc - JSON CLI output utility ntpq Parser
Usage:
specify --ntpq as the first argument if the piped input is coming from ntpq -p
Compatibility:
'linux'
Examples:
$ ntpq -p | jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 1,
"poll": 64,
"reach": 1,
"delay": 23.399,
"offset": -2.805,
"jitter": 2.131,
"state": null
},
{
"remote": "ntp.wdc1.us.lea",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 93.053,
"offset": -0.807,
"jitter": 2.839,
"state": null
},
{
"remote": "clock.team-cymr",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 70.337,
"offset": -2.909,
"jitter": 2.6,
"state": null
},
{
"remote": "mirror1.sjc02.s",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 2,
"poll": 64,
"reach": 1,
"delay": 29.325,
"offset": 1.044,
"jitter": 4.069,
"state": null,
}
]
$ ntpq -pn| jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 66,
"poll": 64,
"reach": 377,
"delay": 22.69,
"offset": -0.392,
"jitter": 2.085,
"state": "+"
},
{
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 90.805,
"offset": 2.84,
"jitter": 1.908,
"state": "-"
},
{
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": 64,
"poll": 64,
"reach": 377,
"delay": 68.699,
"offset": -0.61,
"jitter": 2.576,
"state": "+"
},
{
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 22.654,
"offset": 0.231,
"jitter": 1.964,
"state": "*"
}
]
$ ntpq -pn| jc --ntpq -p -r
[
{
"s": "+",
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": "2",
"t": "u",
"when": "66",
"poll": "64",
"reach": "377",
"delay": "22.690",
"offset": "-0.392",
"jitter": "2.085"
},
{
"s": "-",
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "90.805",
"offset": "2.840",
"jitter": "1.908"
},
{
"s": "+",
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": "2",
"t": "u",
"when": "64",
"poll": "64",
"reach": "377",
"delay": "68.699",
"offset": "-0.610",
"jitter": "2.576"
},
{
"s": "*",
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "22.654",
"offset": "0.231",
"jitter": "1.964"
}
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'ntpq -p command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['ntpq']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"state": string, # space/~ converted to null
"remote": string,
"refid": string,
"st": integer,
"t": string,
"when": integer, # - converted to null
"poll": integer,
"reach": integer,
"delay": float,
"offset": float,
"jitter": float
},
]
"""
for entry in proc_data:
if entry['s'] == '~':
entry['s'] = None
entry['state'] = entry.pop('s')
int_list = ['st', 'when', 'poll', 'reach']
for key in int_list:
if key in entry:
try:
entry[key] = int(entry[key])
except (ValueError):
entry[key] = None
float_list = ['delay', 'offset', 'jitter']
for key in float_list:
if key in entry:
try:
entry[key] = float(entry[key])
except (ValueError):
entry[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
cleandata[0] = 's ' + cleandata[0]
cleandata[0] = cleandata[0].lower()
# delete header delimiter
del cleandata[1]
# separate first character with a space for easier parsing
for i, line in list(enumerate(cleandata[1:])):
if line[0] == ' ':
# fixup for no-state
cleandata[i + 1] = '~ ' + line[1:]
else:
# fixup - realign columns since we added the 's' column
cleandata[i + 1] = line[:1] + ' ' + line[1:]
# fixup for occaisional ip/hostname fields with a space
cleandata[i + 1] = cleandata[i + 1].replace(' (', '_(')
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
if raw:
return raw_output
else:
return process(raw_output)

175
jc/parsers/passwd.py Normal file
View File

@@ -0,0 +1,175 @@
"""jc - JSON CLI output utility /etc/passwd file Parser
Usage:
specify --passwd as the first argument if the piped input is coming from /etc/passwd
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ cat /etc/passwd | jc --passwd -p
[
{
"username": "nobody",
"password": "*",
"uid": -2,
"gid": -2,
"comment": "Unprivileged User",
"home": "/var/empty",
"shell": "/usr/bin/false"
},
{
"username": "root",
"password": "*",
"uid": 0,
"gid": 0,
"comment": "System Administrator",
"home": "/var/root",
"shell": "/bin/sh"
},
{
"username": "daemon",
"password": "*",
"uid": 1,
"gid": 1,
"comment": "System Services",
"home": "/var/root",
"shell": "/usr/bin/false"
},
...
]
$ cat /etc/passwd | jc --passwd -p -r
[
{
"username": "nobody",
"password": "*",
"uid": "-2",
"gid": "-2",
"comment": "Unprivileged User",
"home": "/var/empty",
"shell": "/usr/bin/false"
},
{
"username": "root",
"password": "*",
"uid": "0",
"gid": "0",
"comment": "System Administrator",
"home": "/var/root",
"shell": "/bin/sh"
},
{
"username": "daemon",
"password": "*",
"uid": "1",
"gid": "1",
"comment": "System Services",
"home": "/var/root",
"shell": "/usr/bin/false"
},
...
]
"""
import jc.utils
class info():
version = '1.0'
description = '/etc/passwd file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"username": string,
"password": string,
"uid": integer,
"gid": integer,
"comment": string,
"home": string,
"shell": string
}
]
"""
for entry in proc_data:
int_list = ['uid', 'gid']
for key in int_list:
if key in entry:
try:
key_int = int(entry[key])
entry[key] = key_int
except (ValueError):
entry[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
for entry in cleandata:
if entry.startswith('#'):
continue
output_line = {}
fields = entry.split(':')
output_line['username'] = fields[0]
output_line['password'] = fields[1]
output_line['uid'] = fields[2]
output_line['gid'] = fields[3]
output_line['comment'] = fields[4]
output_line['home'] = fields[5]
output_line['shell'] = fields[6]
raw_output.append(output_line)
if raw:
return raw_output
else:
return process(raw_output)

117
jc/parsers/pip_list.py Normal file
View File

@@ -0,0 +1,117 @@
"""jc - JSON CLI output utility pip-list Parser
Usage:
specify --pip-list as the first argument if the piped input is coming from pip list
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ pip list | jc --pip-list -p
[
{
"package": "ansible",
"version": "2.8.5"
},
{
"package": "antlr4-python3-runtime",
"version": "4.7.2"
},
{
"package": "asn1crypto",
"version": "0.24.0"
},
...
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'pip list command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['pip list', 'pip3 list']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"package": string,
"version": string,
"location": string
}
]
"""
# no further processing
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
linedata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, linedata))
# detect legacy output type
if cleandata[0].find(' (') != -1:
for row in cleandata:
raw_output.append({'package': row.split(' (')[0],
'version': row.split(' (')[1].rstrip(')')})
# otherwise normal table output
else:
# clear separator line
for i, line in reversed(list(enumerate(cleandata))):
if line.find('---') != -1:
cleandata.pop(i)
cleandata[0] = cleandata[0].lower()
if cleandata:
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
if raw:
return raw_output
else:
return process(raw_output)

135
jc/parsers/pip_show.py Normal file
View File

@@ -0,0 +1,135 @@
"""jc - JSON CLI output utility pip-show Parser
Usage:
specify --pip-show as the first argument if the piped input is coming from pip show
Compatibility:
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
Examples:
$ pip show wrapt jc wheel | jc --pip-show -p
[
{
"name": "wrapt",
"version": "1.11.2",
"summary": "Module for decorators, wrappers and monkey patching.",
"home_page": "https://github.com/GrahamDumpleton/wrapt",
"author": "Graham Dumpleton",
"author_email": "Graham.Dumpleton@gmail.com",
"license": "BSD",
"location": "/usr/local/lib/python3.7/site-packages",
"requires": null,
"required_by": "astroid"
},
{
"name": "wheel",
"version": "0.33.4",
"summary": "A built-package format for Python.",
"home_page": "https://github.com/pypa/wheel",
"author": "Daniel Holth",
"author_email": "dholth@fastmail.fm",
"license": "MIT",
"location": "/usr/local/lib/python3.7/site-packages",
"requires": null,
"required_by": null
}
]
"""
import jc.utils
class info():
version = '1.0'
description = 'pip show command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['pip show', 'pip3 show']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"name": string,
"version": string,
"summary": string,
"home_page": string,
"author": string,
"author_email": string,
"license": string,
"location": string,
"requires": string,
"required_by": string
}
]
"""
# no further processing
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
package = {}
linedata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, linedata))
if cleandata:
for row in cleandata:
if row.startswith('---'):
raw_output.append(package)
package = {}
continue
item_key = row.split(': ', maxsplit=1)[0].lower().replace('-', '_')
item_value = row.split(': ', maxsplit=1)[1]
if item_value == '':
item_value = None
package.update({item_key: item_value})
raw_output.append(package)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,12 +1,17 @@
"""jc - JSON CLI output utility ps Parser
Usage:
specify --ps as the first argument if the piped input is coming from ps
ps options supported:
- ef
- axu
Compatibility:
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
Examples:
$ ps -ef | jc --ps -p
@@ -168,6 +173,21 @@ Examples:
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.1'
description = 'ps command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['ps']
__version__ = info.version
def process(proc_data):
@@ -180,7 +200,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -189,7 +209,8 @@ def process(proc_data):
"ppid": integer,
"c": integer,
"stime": string,
"tty": string, # ? = Null
"tty": string, # ? or ?? = Null
"tt": string, # ?? = Null
"time": string,
"cmd": string,
"user": string,
@@ -204,6 +225,14 @@ def process(proc_data):
]
"""
for entry in proc_data:
# change key name '%cpu' to 'cpu_percent'
if '%cpu' in entry:
entry['cpu_percent'] = entry.pop('%cpu')
# change key name '%mem' to 'mem_percent'
if '%mem' in entry:
entry['mem_percent'] = entry.pop('%mem')
# change to int
int_list = ['pid', 'ppid', 'c', 'vsz', 'rss']
for key in int_list:
@@ -225,9 +254,13 @@ def process(proc_data):
entry[key] = None
if 'tty' in entry:
if entry['tty'] == '?':
if entry['tty'] == '?' or entry['tty'] == '??':
entry['tty'] = None
if 'tt' in entry:
if entry['tt'] == '??':
entry['tt'] = None
return proc_data
@@ -243,28 +276,15 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
# code adapted from Conor Heine at:
# https://gist.github.com/cahna/43a1a3ff4d075bcd71f9d7120037a501
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
headers = [h for h in ' '.join(cleandata[0].lower().strip().split()).split() if h]
cleandata[0] = cleandata[0].lower()
# clean up '%cpu' and '%mem' headers
# even though % in a key is valid json, it can make things difficult
headers = ['cpu_percent' if x == '%cpu' else x for x in headers]
headers = ['mem_percent' if x == '%mem' else x for x in headers]
raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:])
raw_output = [dict(zip(headers, r)) for r in raw_data]
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
if raw:
return raw_output

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility route Parser
Usage:
specify --route as the first argument if the piped input is coming from route
Compatibility:
'linux'
Examples:
$ route -ee | jc --route -p
@@ -92,6 +97,21 @@ Examples:
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'route command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['route']
__version__ = info.version
def process(proc_data):
@@ -104,7 +124,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -147,22 +167,15 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd']
if not quiet:
jc.utils.compatibility(__name__, compatible)
# code adapted from Conor Heine at:
# https://gist.github.com/cahna/43a1a3ff4d075bcd71f9d7120037a501
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()[1:]
headers = [h for h in ' '.join(cleandata[0].lower().strip().split()).split() if h]
raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:])
raw_output = [dict(zip(headers, r)) for r in raw_data]
cleandata[0] = cleandata[0].lower()
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
if raw:
return raw_output

183
jc/parsers/shadow.py Normal file
View File

@@ -0,0 +1,183 @@
"""jc - JSON CLI output utility /etc/shadow file Parser
Usage:
specify --shadow as the first argument if the piped input is coming from /etc/shadow
Compatibility:
'linux', 'darwin', 'aix', 'freebsd'
Examples:
$ sudo cat /etc/shadow | jc --shadow -p
[
{
"username": "root",
"password": "*",
"last_changed": 18113,
"minimum": 0,
"maximum": 99999,
"warn": 7,
"inactive": null,
"expire": null
},
{
"username": "daemon",
"password": "*",
"last_changed": 18113,
"minimum": 0,
"maximum": 99999,
"warn": 7,
"inactive": null,
"expire": null
},
{
"username": "bin",
"password": "*",
"last_changed": 18113,
"minimum": 0,
"maximum": 99999,
"warn": 7,
"inactive": null,
"expire": null
},
...
]
$ sudo cat /etc/shadow | jc --shadow -p -r
[
{
"username": "root",
"password": "*",
"last_changed": "18113",
"minimum": "0",
"maximum": "99999",
"warn": "7",
"inactive": "",
"expire": ""
},
{
"username": "daemon",
"password": "*",
"last_changed": "18113",
"minimum": "0",
"maximum": "99999",
"warn": "7",
"inactive": "",
"expire": ""
},
{
"username": "bin",
"password": "*",
"last_changed": "18113",
"minimum": "0",
"maximum": "99999",
"warn": "7",
"inactive": "",
"expire": ""
},
...
]
"""
import jc.utils
class info():
version = '1.0'
description = '/etc/shadow file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'darwin', 'aix', 'freebsd']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"username": string,
"password": string,
"last_changed": integer,
"minimum": integer,
"maximum": integer,
"warn": integer,
"inactive": integer,
"expire": integer
}
]
"""
for entry in proc_data:
int_list = ['last_changed', 'minimum', 'maximum', 'warn', 'inactive', 'expire']
for key in int_list:
if key in entry:
try:
key_int = int(entry[key])
entry[key] = key_int
except (ValueError):
entry[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
# Clear any blank lines
cleandata = list(filter(None, cleandata))
if cleandata:
for entry in cleandata:
if entry.startswith('#'):
continue
output_line = {}
fields = entry.split(':')
output_line['username'] = fields[0]
output_line['password'] = fields[1]
output_line['last_changed'] = fields[2]
output_line['minimum'] = fields[3]
output_line['maximum'] = fields[4]
output_line['warn'] = fields[5]
output_line['inactive'] = fields[6]
output_line['expire'] = fields[7]
raw_output.append(output_line)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,11 +1,17 @@
"""jc - JSON CLI output utility ss Parser
Usage:
specify --ss as the first argument if the piped input is coming from ss
Limitations:
Extended information options like -e and -p are not supported and may cause parsing irregularities
Compatibility:
'linux'
Examples:
$ sudo ss -a | jc --ss -p
@@ -244,6 +250,20 @@ import string
import jc.utils
class info():
version = '1.0'
description = 'ss command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['ss']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -254,7 +274,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -315,14 +335,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
contains_colon = ['nl', 'p_raw', 'raw', 'udp', 'tcp', 'v_str', 'icmp6']
raw_output = []

View File

@@ -1,7 +1,12 @@
"""jc - JSON CLI output utility stats Parser
"""jc - JSON CLI output utility stat Parser
Usage:
specify --stats as the first argument if the piped input is coming from stats
specify --stat as the first argument if the piped input is coming from stat
Compatibility:
'linux'
Examples:
@@ -98,6 +103,20 @@ Examples:
import jc.utils
class info():
version = '1.0'
description = 'stat command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['stat']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -108,7 +127,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -167,14 +186,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility systemctl Parser
Usage:
specify --systemctl as the first argument if the piped input is coming from systemctl
Compatibility:
'linux'
Examples:
$ systemctl -a | jc --systemctl -p
@@ -34,6 +39,20 @@ Examples:
import jc.utils
class info():
version = '1.0'
description = 'systemctl command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['systemctl']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -44,7 +63,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -72,14 +91,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, systemctlbsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
linedata = data.splitlines()
# Clear any blank lines

View File

@@ -1,8 +1,13 @@
"""jc - JSON CLI output utility systemctl-lj Parser
Usage:
specify --systemctl-lj as the first argument if the piped input is coming from systemctl list-jobs
Compatibility:
'linux'
Examples:
$ systemctl list-jobs| jc --systemctl-lj -p
@@ -53,6 +58,20 @@ Examples:
import jc.utils
class info():
version = '1.0'
description = 'systemctl list-jobs command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['systemctl list-jobs']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
@@ -63,7 +82,7 @@ def process(proc_data):
Returns:
dictionary structured data with the following schema:
List of dictionaries. Structured data with the following schema:
[
{
@@ -98,14 +117,10 @@ def parse(data, raw=False, quiet=False):
Returns:
dictionary raw or processed structured data
List of dictionaries. Raw or processed structured data.
"""
# compatible options: linux, darwin, cygwin, win32, aix, systemctlbsd
compatible = ['linux']
if not quiet:
jc.utils.compatibility(__name__, compatible)
jc.utils.compatibility(__name__, info.compatible)
linedata = data.splitlines()
# Clear any blank lines

Some files were not shown because too many files have changed in this diff Show More