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

Compare commits

...

291 Commits

Author SHA1 Message Date
Kelly Brazil
5023e5be4c Dev v1.23.3 (#426)
* make certificate search more robust to different line endings

* use license_files instead of license_file which is deprecated

* version bump

* parsing extra options -e, -o, -p

* fix for extra opts and different field length at option -[aeop]

* test integration for extra opts -e -o -p

* formatting and use ast.literal_eval instead of eval

* doc update

* doc update

* Add a parser to parse mounted encrypted veracrypt volumes (fixes #403)

* update compatibility warning message

* netstat windows parser

* tests

* Windows route parser

* tests

* id should be a string

* add veracrypt parser and docs

* formatting

* doc update

* lsattr parser

* Update test_lsattr.py

* changed keys to lowercase

* changed info

* support missing data for stat

* doc update

* doc update

* doc update

* ensure compatibility warning prints even with no data

* improve compatibility message

* add support for dig +nsid option

* New parser: srt (#415)

* srt parser

* changed the parser to support more complex cases

* doc updates

* Adding certificate request parser (#416)

* Adding certificate request parser

* Adding the CSR type for Windows-style CSR

---------

Co-authored-by: Stg22 <stephane.for.test@gmail.com>

* doc update

* add csr tests

* Last -x (#422)

* Refactored the parser

* last -x support

* doc update

* fix for ping on linux with missing hostname

* allow less strict email decoding with a warning.

* doc update

* use explicit ascii decode with backslashreplace

* doc update

* use jc warning function instead of print for warning message

* last -x shutdown fix (#423)

* inject quiet setting into asn1crypto library

* Parse appearance and modalias lines for mouse devices (fixes #419) (#425)

The bluetoothctl device parser is implemented so that it aborts the parsing
process immediately returning what it has collected so far. This is because
the parser should work in hydrid way to support outputs comming from bluetoothctl
devices and bluetoothctl info calls.

* doc update

* doc update

---------

Co-authored-by: gerd <gerd.augstein@gmail.com>
Co-authored-by: Jake Ob <iakopap@gmail.com>
Co-authored-by: Mevaser <mevaser.rotner@gmail.com>
Co-authored-by: M.R <69431152+YeahItsMeAgain@users.noreply.github.com>
Co-authored-by: Stg22 <46686290+Stg22@users.noreply.github.com>
Co-authored-by: Stg22 <stephane.for.test@gmail.com>
2023-06-21 15:48:23 -07:00
Kelly Brazil
5527d22459 Merge pull request #398 from kellyjonbrazil/dev
Dev v1.23.2
2023-04-30 10:40:21 -07:00
Kelly Brazil
9d567c2e70 python 3.6 fix 2023-04-30 10:13:00 -07:00
Kelly Brazil
39c03a15d5 doc update 2023-04-30 09:34:22 -07:00
Kelly Brazil
5e6d2562f9 add certbot command parser 2023-04-29 16:34:23 -07:00
Kelly Brazil
7009d5a014 fix for incorrect insertion and deletion parsing 2023-04-22 14:04:00 -07:00
Kelly Brazil
42f9ddabb9 change bluetoothctl compatibility 2023-04-21 14:22:23 -07:00
Kelly Brazil
30efb5afc0 fix for multiline description 2023-04-18 11:23:49 -07:00
Kelly Brazil
786dc76c09 fix for battery not charging message 2023-04-17 18:12:57 -07:00
Kelly Brazil
fc48874a5d pytest warning fixes 2023-04-17 15:15:40 -07:00
Kelly Brazil
67164e7b23 fix mypy issues 2023-04-16 18:50:40 -07:00
Kelly Brazil
3db9774ac6 doc update 2023-04-16 11:46:21 -07:00
Kelly Brazil
03aef93d9a Merge pull request #392 from tzeikob/bluetoothctl-parser
Add parser for the bluetoothctl utility
2023-04-16 11:39:54 -07:00
Jake Ob
9b7e3de3ed Fix broken unit tests for the bluetoothctl parser 2023-04-16 20:52:29 +03:00
Jake Ob
291b6b061a Parse numeric fields to their actual numeric value 2023-04-16 20:42:48 +03:00
Jake Ob
08496533e2 Process data only if data is given 2023-04-16 20:19:15 +03:00
Jake Ob
f8dceb5046 Fix minor typo in documentation 2023-04-16 20:15:24 +03:00
Jake Ob
240ed4047f Add parser for the bluetoothctl utility 2023-04-14 18:23:45 +03:00
Kelly Brazil
0bf6f7cd7c fix incorrect variable parsing when wildcard schedule 2023-04-02 13:18:16 -07:00
Kelly Brazil
313bd86e3e doc update 2023-04-02 12:57:56 -07:00
Kelly Brazil
56259d5605 fix for dashes in name 2023-04-02 12:57:50 -07:00
Kelly Brazil
8a4885c1fe Merge pull request #384 from six3six/patch-1
Fix iwconfig re_interface regex
2023-03-31 08:40:00 -07:00
Louis Desplanche
5b06f84917 Fix iwconfig re_interface regex
Small fix of re_interface in iwconfig.py.
When the network SSID contains a "-" character, the network interface was ignored.
2023-03-31 11:15:31 +02:00
Kelly Brazil
37a1428914 Merge pull request #381 from kellyjonbrazil/dev
Dev v1.23.1
2023-03-23 20:16:11 -04:00
Kelly Brazil
bff065daf3 doc update 2023-03-23 16:41:50 -07:00
Kelly Brazil
c60d899f31 ignore non-parser-plugin python files in plugin directory 2023-03-23 16:40:13 -07:00
Kelly Brazil
fb7c390506 add lsusb tests 2023-03-23 06:43:06 -07:00
Kelly Brazil
22afb69573 doc update 2023-03-22 16:47:45 -07:00
Kelly Brazil
be51304c9c add support for CDC MBIM and CDC MBIM Extended 2023-03-22 16:43:57 -07:00
Kelly Brazil
44f83d800f doc update 2023-03-19 12:49:25 -07:00
Kelly Brazil
bf07973d90 doc update 2023-03-19 12:39:28 -07:00
Kelly Brazil
11e94b686c mypy fix 2023-03-18 15:47:19 -07:00
Kelly Brazil
c68bf674a1 add py.typed file to wheel 2023-03-18 15:43:22 -07:00
Kelly Brazil
dbbc310082 Merge pull request #378 from jwilk-forks/proc-status-umask
Make umask optional in /proc/PID/status
2023-03-18 22:37:13 +00:00
Kelly Brazil
e861f4a597 Merge pull request #379 from jwilk-forks/spelling
Fix typo
2023-03-18 22:25:21 +00:00
Kelly Brazil
049e93707c doc update 2023-03-18 15:16:02 -07:00
Kelly Brazil
164294ecb7 add integer and float conversions 2023-03-18 15:14:59 -07:00
Jakub Wilk
22ef489795 fix typo 2023-03-18 11:07:15 +01:00
Jakub Wilk
8f9d650f6c make umask optional in /proc/PID/status
Zombie processes don't have the umask field available.
2023-03-18 10:28:05 +01:00
Kelly Brazil
7e134a63bd add support for the timesync-status option 2023-03-15 06:58:31 -07:00
Kelly Brazil
9b5c25cb5b fix for rtc configured as UTC 2023-03-13 19:47:38 -07:00
Kelly Brazil
894946b207 doc update 2023-03-05 10:07:23 -08:00
Kelly Brazil
92ad2068db version bump 2023-03-05 10:06:54 -08:00
Kelly Brazil
59662a1500 fix for lines that start with tab 2023-03-05 10:04:00 -08:00
Kelly Brazil
125b88a2ca Merge pull request #371 from kellyjonbrazil/master
sync to dev
2023-03-05 17:59:09 +00:00
Kelly Brazil
79fce8c769 doc update 2023-02-27 17:37:49 -08:00
Kelly Brazil
a4a53f8b3b Merge pull request #368 from kellyjonbrazil/dev
Dev v1.23.0
2023-02-27 15:13:57 -08:00
Kelly Brazil
743e1ae90f doc update 2023-02-27 15:01:00 -08:00
Kelly Brazil
dbcff80907 add zpool tests 2023-02-27 13:44:16 -08:00
Kelly Brazil
6e10965aed doc update 2023-02-21 17:19:17 -08:00
Kelly Brazil
0c8c4a9c53 formatting 2023-02-21 17:18:24 -08:00
Kelly Brazil
7632541a1e Merge pull request #365 from tzeikob/xrandr-edid-364
Modify the xrandr parser to extract display model info from EDID #364
2023-02-21 17:04:46 -08:00
Kelly Brazil
a213ad9a85 doc update 2023-02-21 15:50:09 -08:00
Kelly Brazil
15ac5a9004 fix for crontab files with only shortcut entries 2023-02-21 15:44:55 -08:00
Jake Ob
0658668eb0 Fix broken TypedDict compatibility with older versions of python
By missing to declare the Model as a generic dictionary type we cause
the script to fail because the TypedDict is not supported by older
versions of python (e.g. 3.6, 3.7).
2023-02-21 14:43:10 +02:00
Kelly Brazil
ccef69ac37 add ubuntu16 tests 2023-02-20 12:04:45 -08:00
Kelly Brazil
64676fda2e fix for older linux style output 2023-02-20 11:56:20 -08:00
Jake Ob
6ea2d776ae Add unit tests for xrandr --properties outputs 2023-02-17 16:25:41 +02:00
Jake Ob
98ced9616c Modify xrandr parser to extract model info from EDID (#364)
This change will make the xrandr parser to work also with outputs from
`xrandr --properties`, where the option `--properties` enables xrandr
to return the EDID data of each output device. The parser is expected
to remain backward compatible for regular xrandr outputs. The extra info
that will be added to every device object is:

```json
{
  "model_name": "str",
  "product_id": "str",
  "serial_number": "str"
}
```

Because the EDID data come encoded in a hexadecimal string, we have to
decode them by vendoring the pyedid (https://github.com/jojonas/pyedid) library.

Fixes: #364
2023-02-17 16:09:50 +02:00
Kelly Brazil
ae19183803 add test for is_current fix 2023-02-13 18:17:14 -08:00
Kelly Brazil
8536514baf add test for output with extra spaces that caused infinite loops 2023-02-13 18:09:10 -08:00
Kelly Brazil
81982a9f79 doc updagte 2023-02-12 18:30:31 -08:00
Kelly Brazil
1acbb2f096 Merge pull request #361 from tzeikob/reflect-360
Move the reflect value in its own key (xrandr) #360
2023-02-12 18:28:37 -08:00
Jake Ob
80fb4d40a5 Add unit test to assert devices in reflect mode 2023-02-09 21:22:34 +02:00
Kelly Brazil
c972dd1aac Merge pull request #362 from jpmat296/master
Improve accepted formats in proc_pid_smaps
2023-02-09 09:51:26 -08:00
Jean-Pierre Matsumoto
9dde65c25c Improve accepted formats in proc_pid_smaps 2023-02-07 14:57:15 +01:00
Jake Ob
7486b0c7cd Move the reflect value in its own key (xrandr)
Currently the reflect value of a device is included in the rotation
key as a combination of both rotation and reflection (e.g. normal X axis).
With this modification we move the reflection value to its own key in the
JSON document like so:

```json
{
  ...
  "rotation": "...",
  "reflection": "...,
  ...
}
```

Fixes: issue #360
2023-02-07 13:02:21 +02:00
Kelly Brazil
5c7a520a0b formatting 2023-02-05 13:04:32 -08:00
Kelly Brazil
193ddf71f8 fix typos 2023-02-05 09:52:59 -08:00
Kelly Brazil
c46fe9816c doc update 2023-02-05 09:49:32 -08:00
Kelly Brazil
aada5f0794 add int conversions 2023-02-04 19:04:43 -08:00
Kelly Brazil
5c7bf363a6 add schema and docs 2023-02-04 18:51:31 -08:00
Kelly Brazil
00b74be540 version bump 2023-02-04 17:37:56 -08:00
Kelly Brazil
96cb01f57a fix zpool-status for multi-line fields 2023-02-04 17:37:48 -08:00
Kelly Brazil
adf5f403ae regex fix for infinite loop? 2023-02-04 14:37:03 -08:00
Kelly Brazil
1c09c95c71 doc update 2023-02-04 11:26:41 -08:00
Kelly Brazil
64f442d743 fix for is_current? 2023-02-04 11:20:48 -08:00
Kelly Brazil
cd8d43446b add zpool-status parser 2023-02-02 15:57:15 -08:00
Kelly Brazil
7361eac1a4 formatting 2023-01-31 17:02:04 -08:00
Kelly Brazil
9d41f0a938 doc update 2023-01-31 17:00:42 -08:00
Kelly Brazil
00274c15df add process conversions 2023-01-31 16:52:56 -08:00
Kelly Brazil
d0b8a91f94 add zpool-iostat parser 2023-01-31 11:59:19 -08:00
Kelly Brazil
098e8dbef6 doc update 2023-01-31 11:59:06 -08:00
Kelly Brazil
ec29b8bbc6 add test for acpi fix for never fully discharge state 2023-01-31 09:51:23 -08:00
Kelly Brazil
1d8f83b8c6 add ver parser tests 2023-01-31 09:44:23 -08:00
Kelly Brazil
12c4419c6a doc update 2023-01-31 08:30:37 -08:00
Kelly Brazil
b134c53f33 add ssh_conf tests 2023-01-31 08:29:43 -08:00
Kelly Brazil
23ff19fdb5 add slicer tests 2023-01-31 06:48:37 -08:00
Kelly Brazil
7a43ba631b fix tests for slice info metadata 2023-01-30 08:59:54 -08:00
Kelly Brazil
2beb26f3e3 add slice info to Metadata output 2023-01-30 08:52:22 -08:00
Kelly Brazil
4b55f49e99 formatting 2023-01-30 08:11:21 -08:00
Kelly Brazil
c0239a771c clarify parser argument quote wrapping code 2023-01-27 16:28:55 -08:00
Kelly Brazil
bc4738e900 don't quote spaces in command arguments 2023-01-27 15:58:01 -08:00
Kelly Brazil
1c76caf59b formatting 2023-01-27 15:22:36 -08:00
Kelly Brazil
0679951d4a add <nobr> tag 2023-01-27 15:17:41 -08:00
Kelly Brazil
df7aee9e4b doc update 2023-01-27 14:47:08 -08:00
Kelly Brazil
a8d97a2521 add slice info to help and doc update 2023-01-27 11:41:21 -08:00
Kelly Brazil
9370b336d8 add slice to man page 2023-01-27 11:31:16 -08:00
Kelly Brazil
118f98222a change restapi link 2023-01-27 08:15:53 -08:00
Kelly Brazil
dc997821f4 ad jc-api demo link 2023-01-27 08:12:07 -08:00
Kelly Brazil
aef0fdb435 formatting 2023-01-27 08:02:07 -08:00
Kelly Brazil
21ee3c0e78 clarify slice usage 2023-01-27 08:01:32 -08:00
Kelly Brazil
d6c665f74b add both negative slice description 2023-01-26 17:06:07 -08:00
Kelly Brazil
79305a50d0 formatting 2023-01-26 16:59:15 -08:00
Kelly Brazil
e758aa41ef formatting 2023-01-26 16:49:27 -08:00
Kelly Brazil
910cb34b09 formatting 2023-01-26 16:49:09 -08:00
Kelly Brazil
976fea4eb2 Formatting 2023-01-26 16:46:54 -08:00
Kelly Brazil
81447ec9e6 formatting 2023-01-26 16:44:26 -08:00
Kelly Brazil
61b8e9f7b5 doc update 2023-01-26 16:24:32 -08:00
Kelly Brazil
8e86a04448 add slicing info 2023-01-26 16:18:54 -08:00
Kelly Brazil
f23715a783 formatting 2023-01-26 08:53:50 -08:00
Kelly Brazil
fa693a8bb1 formatting 2023-01-26 08:53:06 -08:00
Kelly Brazil
103168c25b add integer conversions 2023-01-26 08:48:59 -08:00
Kelly Brazil
ae7ed4eec5 doc update 2023-01-26 08:48:46 -08:00
Kelly Brazil
caa516db72 formatting 2023-01-25 16:59:49 -08:00
Kelly Brazil
f05c3d6113 docstring update 2023-01-25 16:57:15 -08:00
Kelly Brazil
5d872b1535 docstring update: add see also section. 2023-01-25 16:30:20 -08:00
Kelly Brazil
1559cd9f5c fixup patch numbers 2023-01-25 16:13:33 -08:00
Kelly Brazil
a5a87c7da1 add ver parser 2023-01-25 15:58:27 -08:00
Kelly Brazil
0e6cec62c1 remove unneeded slicer syntax check 2023-01-23 16:53:06 -08:00
Kelly Brazil
3bb1d89165 fix multiple slicer warnings 2023-01-23 16:50:41 -08:00
Kelly Brazil
f5f5f102fb full functioning slicer feature 2023-01-23 16:13:17 -08:00
Kelly Brazil
0c82fe7e4d add slicer functionality 2023-01-23 13:57:48 -08:00
Kelly Brazil
13ffe8a84d doc update 2023-01-22 12:44:16 -08:00
Kelly Brazil
4c6eebaa33 doc update 2023-01-22 10:37:27 -08:00
Kelly Brazil
f8fbb2dce2 use derivative of sshd_conf parser instead of paramiko 2023-01-22 10:36:29 -08:00
Kelly Brazil
dbfe682674 fix for never fully discharging state 2023-01-22 08:57:50 -08:00
Kelly Brazil
2a148d44a1 add host to objects 2023-01-21 17:00:22 -08:00
Kelly Brazil
0648d2e9e3 don't interpolate local host values 2023-01-21 16:37:27 -08:00
Kelly Brazil
ac9128fa0c add ssh-conf parser 2023-01-21 13:10:45 -08:00
Kelly Brazil
4d7a872670 version bump 2023-01-21 10:56:45 -08:00
Kelly Brazil
07f716b254 Merge pull request #355 from kellyjonbrazil/master
sync to dev
2023-01-21 10:53:03 -08:00
Kelly Brazil
b0d6a7307c Merge pull request #353 from kellyjonbrazil/dev
Dev v1.22.5
2023-01-11 14:39:13 -08:00
Kelly Brazil
53ad793ff8 doc update 2023-01-11 11:17:47 -08:00
Kelly Brazil
ea4332d8e4 add ini-dup tests 2023-01-10 16:06:05 -08:00
Kelly Brazil
5c5ff9324f update multi-line value behavior 2023-01-09 08:31:21 -08:00
Kelly Brazil
2ab6352fdb doc update 2023-01-08 19:54:32 -08:00
Kelly Brazil
56dcbaf40c doc update 2023-01-08 19:53:21 -08:00
Kelly Brazil
029b5abcac add ini-dup parser 2023-01-08 19:46:13 -08:00
Kelly Brazil
32521ac91a doc update 2023-01-08 10:55:48 -08:00
Kelly Brazil
bf88407902 remove special DEFAULT section handling 2023-01-08 10:55:44 -08:00
Kelly Brazil
63cf47db63 doc update 2023-01-06 13:37:34 -08:00
Kelly Brazil
9970866b3b Merge pull request #350 from davemq/arp_aix
AIX ARP support
2023-01-06 13:34:44 -08:00
Dave Marquardt
d61941b276 Merge branch 'dev' into arp_aix 2023-01-06 15:14:39 -06:00
Dave Marquardt
081fdb8026 Updated AIX ARP test comments 2023-01-06 15:13:03 -06:00
Dave Marquardt
f64dfbf79d Update comments about AIX ARP 2023-01-06 15:10:02 -06:00
Dave Marquardt
5fb73f4ad5 Added AIX support for ARP, along with AIX ARP test support 2023-01-06 14:53:50 -06:00
Dave Marquardt
1c16d32420 Added test data for AIX ARP 2023-01-06 14:51:09 -06:00
Kelly Brazil
e367e0d714 doc update 2023-01-06 09:28:13 -08:00
Kelly Brazil
4046649e32 toml tests and doc update 2023-01-06 09:11:00 -08:00
Kelly Brazil
77fcfe439c remove unused list 2023-01-06 08:50:03 -08:00
Kelly Brazil
71d1355419 formatting 2023-01-06 08:36:48 -08:00
Kelly Brazil
d1b270f336 formatting 2023-01-06 08:26:42 -08:00
Dave Marquardt
9190a08332 More AIX permanent ARP entry fixes 2023-01-06 10:25:04 -06:00
Dave Marquardt
3fae50e305 Handle permanent ARP entries on AIX 2023-01-06 10:21:32 -06:00
Dave Marquardt
3582497ed4 Fix interface parsing for incomplete ARP entry on AIX 2023-01-06 10:16:13 -06:00
Dave Marquardt
19a67daabf rewrite check for incomplete ARP entries 2023-01-06 10:12:50 -06:00
Dave Marquardt
02a7e5fd8a Updated ARP incomplete handling for AIX 2023-01-06 10:08:33 -06:00
Dave Marquardt
df72b16022 Start to fix AIX ARP support 2023-01-06 10:00:58 -06:00
Kelly Brazil
61bdc13810 doc update 2023-01-05 17:05:03 -08:00
Kelly Brazil
1350a34316 beautify process function 2023-01-05 16:59:22 -08:00
Kelly Brazil
7cfe68b96a beautify remove_quotes function 2023-01-05 16:55:53 -08:00
Kelly Brazil
7a93a61f54 move unsectioned k/v's to the top level 2023-01-05 15:44:21 -08:00
Kelly Brazil
362977e598 comment unused objects 2023-01-05 14:26:01 -08:00
Kelly Brazil
5cac897beb zipinfo fix for paths with spaces 2023-01-05 12:00:20 -08:00
Kelly Brazil
cad94cc6b3 formatting and doc update 2023-01-05 11:46:14 -08:00
Kelly Brazil
fe4e429e85 Merge pull request #349 from davemq/mount_aix
Add AIX mount support
2023-01-05 11:39:42 -08:00
Kelly Brazil
d83b10e2d5 doc update 2023-01-05 11:27:49 -08:00
Kelly Brazil
bd2a757fcd more refactoring 2023-01-05 11:27:00 -08:00
Dave Marquardt
358b69a4cb Merge branch 'dev' into mount_aix 2023-01-05 11:06:00 -06:00
Dave Marquardt
08821a1454 Removed unneeded imports from mount parser 2023-01-05 10:57:23 -06:00
Kelly Brazil
90277c1d87 formatting 2023-01-05 08:54:40 -08:00
Dave Marquardt
a51e702f77 Added AIX mount test 2023-01-05 10:53:02 -06:00
Dave Marquardt
466e37128b Merge branch 'dev' into mount_aix 2023-01-05 10:32:47 -06:00
Dave Marquardt
f1ea61388f Added AIX mount support 2023-01-05 10:28:01 -06:00
Kelly Brazil
72c11fda3a more refactoring 2023-01-05 08:00:18 -08:00
Kelly Brazil
d6645983ef more refactoring 2023-01-04 20:54:31 -08:00
Kelly Brazil
01e911ecdb remove more type annotations 2023-01-04 19:17:29 -08:00
Kelly Brazil
12c0b3d889 remove more type annotations 2023-01-04 19:13:12 -08:00
Kelly Brazil
c1075e40b7 remove more type hinting for python 3.6 2023-01-04 19:09:41 -08:00
Kelly Brazil
fabe3f01b7 remove type annotations for python 3.6 compatibility 2023-01-04 19:00:49 -08:00
Kelly Brazil
3a2ff61899 fix lsusb for extra hub port info and add videocontrol and videostreaming sections 2023-01-04 18:27:51 -08:00
Kelly Brazil
aeff94d272 add toml parser 2023-01-04 18:26:13 -08:00
Kelly Brazil
c94f5d83fa fix kv and ini parsers to only remove 1 quote from beginning and end 2023-01-03 13:26:52 -08:00
Kelly Brazil
b0756fa0f9 doc update 2023-01-03 13:05:51 -08:00
Kelly Brazil
6c85abd57b doc update 2023-01-03 13:04:13 -08:00
Kelly Brazil
7659ae94bd formatting 2023-01-03 12:59:10 -08:00
Kelly Brazil
e306e81e43 formatting 2023-01-03 12:57:04 -08:00
Kelly Brazil
6d5768b26b simplify code and doc update 2023-01-03 12:55:38 -08:00
Kelly Brazil
cee9f8bf32 remove duplicate code. add tests 2023-01-03 12:44:12 -08:00
Kelly Brazil
b8e2678c01 doc update 2023-01-03 12:30:23 -08:00
Kelly Brazil
b0fe96ed03 doc update 2023-01-03 12:28:26 -08:00
Kelly Brazil
bb65ec380b separate kv and ini parsers. add fake top-level section in ini files that are missing it. 2023-01-03 12:11:05 -08:00
Kelly Brazil
ae6248227b version bump 2023-01-03 11:53:57 -08:00
Kelly Brazil
36ce3c791d Merge pull request #343 from kellyjonbrazil/dev
Dev v1.22.4
2022-12-30 13:29:57 -08:00
Kelly Brazil
5d639db5a8 Merge branch 'master' into dev 2022-12-30 13:24:24 -08:00
Kelly Brazil
63161ffdbb doc update 2022-12-30 13:11:54 -08:00
Kelly Brazil
cf11c71831 move import to except block 2022-12-30 11:53:09 -08:00
Kelly Brazil
048f8c1f4b formatting 2022-12-30 11:49:20 -08:00
Kelly Brazil
b6b42d9071 doc update 2022-12-30 11:46:40 -08:00
Kelly Brazil
d43863ee9f delete the tempfile after use 2022-12-30 11:32:14 -08:00
Kelly Brazil
177d10577f create NamedTemporaryFile with delete=False for Windows compatibilty 2022-12-30 11:17:52 -08:00
Kelly Brazil
47d8e163de patch for windows compatibility: can only open tempfile once 2022-12-30 11:06:45 -08:00
Kelly Brazil
e49c621e59 try writing to file as bytes for windows compatibility 2022-12-30 10:44:46 -08:00
Kelly Brazil
5e32a6d828 fix for python 3.10+ compatibility 2022-12-30 10:37:12 -08:00
Kelly Brazil
b1358a7eca add nextstep plist support. using the pbPlist library 2022-12-30 10:27:03 -08:00
Kelly Brazil
ba89092e12 formatting 2022-12-29 14:52:33 -08:00
Kelly Brazil
f855420a82 doc update 2022-12-29 09:25:31 -08:00
Kelly Brazil
1589a81945 fix issue with text serial numbers in certificates 2022-12-28 21:59:38 -08:00
Kelly Brazil
eec2583cb2 formatting 2022-12-27 15:59:43 -08:00
Kelly Brazil
481c6a8de2 doc update 2022-12-27 14:01:03 -08:00
Kelly Brazil
68717e8493 add parser metadata tags and category view to help 2022-12-27 13:59:10 -08:00
Kelly Brazil
c524d37136 use ubuntu-20.04 instead of latest for python 3.6 2022-12-23 10:25:12 -08:00
Kelly Brazil
6674f549f2 version bumps and doc update 2022-12-23 10:14:19 -08:00
Kelly Brazil
ba371ec730 fix proc signature for pid_stat so hack comm names with parenthesis are handled correctly. 2022-12-23 10:08:19 -08:00
Kelly Brazil
44d1d52426 fix test for python 3.6 2022-12-23 09:40:26 -08:00
Kelly Brazil
edcca4fb96 remove re type annotations for python 3.6 compatibility 2022-12-23 09:23:51 -08:00
Kelly Brazil
6fbf9458d1 Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2022-12-23 09:21:29 -08:00
Kelly Brazil
a476e4639b force test 2022-12-23 09:21:27 -08:00
Kelly Brazil
5534a1c755 change to ubuntu-20.04 for python 3.6 tests 2022-12-23 09:20:32 -08:00
Kelly Brazil
c45518db70 Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2022-12-23 09:17:44 -08:00
Kelly Brazil
55480c059a python 3.6 compatibility: remove re.Match type annotation 2022-12-23 09:17:42 -08:00
Kelly Brazil
04a2af8681 add python 3.6 to tests 2022-12-23 09:14:19 -08:00
Kelly Brazil
71f672a0e0 add python 3.6 to tests 2022-12-23 09:13:00 -08:00
Kelly Brazil
33c40874fa version bump and add iwconfig parser 2022-12-23 09:12:09 -08:00
Kelly Brazil
b3ced64672 Merge pull request #334 from vrince/iwconfig-parser
add new iwconfig parser
2022-12-23 09:00:22 -08:00
Thomas Vincent
a60bf00d54 iwconfig: add test with many interface 2022-12-21 17:25:57 -05:00
Thomas Vincent
8d9a2744af iwconfig: add example in the docstring 2022-12-21 17:15:25 -05:00
Thomas Vincent
bcd7bac950 iwconfig: add to parser list + move test fixture to generic folder 2022-12-21 17:12:20 -05:00
Thomas Vincent
e996b3a9f6 add iwconfig raw vs process + tests 2022-12-19 22:36:48 -05:00
Thomas Vincent
e207cccdc5 fix copy/paste mess in regex 2022-12-19 22:23:10 -05:00
Thomas Vincent
9776dd1082 add new iwconfig parser 2022-12-19 22:13:58 -05:00
Kelly Brazil
bcff00799f Merge pull request #328 from kellyjonbrazil/dev
Dev v1.22.3
2022-12-16 15:31:16 -06:00
Kelly Brazil
0dc76621bc doc update 2022-12-16 12:54:07 -08:00
Kelly Brazil
1040c5706f split prefix and ports. remove utc timestamps 2022-12-14 11:55:46 -08:00
Kelly Brazil
265d08e3bd doc update 2022-12-13 17:32:12 -08:00
Kelly Brazil
491fce7052 add openvpn-status.log file parser 2022-12-13 17:31:05 -08:00
Kelly Brazil
3404bc4840 add pgpass tests 2022-12-13 14:57:22 -08:00
Kelly Brazil
064e3f6ac0 try changing test dates for windows compatibility 2022-12-13 14:11:12 -08:00
Kelly Brazil
71f0c4f9da doc update 2022-12-13 13:46:33 -08:00
Kelly Brazil
18143608dc doc update 2022-12-13 13:30:50 -08:00
Kelly Brazil
83a6d92449 fix tests for additional timestamps 2022-12-13 13:30:31 -08:00
Kelly Brazil
ac1f690c54 add epoch timestamps 2022-12-13 13:29:54 -08:00
Kelly Brazil
b063f1bfb4 add google big table time format 2022-12-13 13:10:34 -08:00
Kelly Brazil
4c5caa7b86 add iso attribute to timestamp 2022-12-13 12:47:31 -08:00
Kelly Brazil
85edda6e5f Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2022-12-13 12:15:28 -08:00
Kelly Brazil
6e1a4a103c formatting and typing fixes 2022-12-13 12:13:27 -08:00
Kelly Brazil
2879c084e5 doc update 2022-12-13 09:01:13 -08:00
Kelly Brazil
4ecc94e531 formatting and typing fixes 2022-12-13 09:01:04 -08:00
Kelly Brazil
b8ef583b93 Merge pull request #327 from graipher/master
Add parser for cbt
2022-12-13 10:40:46 -06:00
Andreas Weiden
fd61e19135 Add raw schema 2022-12-12 19:48:33 +01:00
Andreas Weiden
79011465af Fix docstring 2022-12-12 19:46:45 +01:00
Andreas Weiden
27acedf8b7 Add newlines at end of files 2022-12-12 15:43:27 +01:00
Andreas Weiden
532c37140c Move test stuff to fixtures 2022-12-12 15:33:40 +01:00
Andreas Weiden
7f4a951065 Add parser to table in readme 2022-12-12 15:18:39 +01:00
Andreas Weiden
b9fb7fad9c Add parser for cbt 2022-12-12 15:10:59 +01:00
Kelly Brazil
be85d78f55 doc update 2022-12-05 14:54:23 -08:00
Kelly Brazil
23e02090e0 add pgpass parser 2022-12-05 14:43:48 -08:00
Kelly Brazil
50f2a811ad doc update 2022-12-05 12:43:45 -08:00
Kelly Brazil
28ee448c44 remove unneeded type ignore comments 2022-12-05 12:42:55 -08:00
Kelly Brazil
688a2099b5 relax JSONDictType - unions and Dicts cause a lot of friction 2022-12-05 12:15:35 -08:00
Kelly Brazil
6f0a53ed02 fix doc title 2022-12-02 16:10:00 -08:00
Kelly Brazil
8a14de663e doc update 2022-12-02 15:16:46 -08:00
Kelly Brazil
09344e938a add lane info lines 2022-12-02 15:16:07 -08:00
Kelly Brazil
bf41140322 fix tests for missing ipv6 addresses 2022-12-02 11:16:13 -08:00
Kelly Brazil
689a85db9b fix for missing ipv6 addresses and scope_id 2022-12-02 11:09:17 -08:00
Kelly Brazil
5e0d206e7a minor cleanup 2022-11-22 13:18:08 -08:00
Kelly Brazil
61addd7950 doc update 2022-11-22 13:12:40 -08:00
Kelly Brazil
60bb9e2aa9 doc update 2022-11-22 13:11:41 -08:00
Kelly Brazil
842fbbab64 formatting 2022-11-22 13:11:10 -08:00
Kelly Brazil
bbd227caf4 tighten up blank line checking 2022-11-22 13:10:58 -08:00
Kelly Brazil
975b4f5e4f add clf-s parser tests 2022-11-22 13:10:15 -08:00
Kelly Brazil
06840931ba doc update 2022-11-21 16:54:42 -08:00
Kelly Brazil
9f4327f517 add clf-s streaming parser 2022-11-21 16:54:13 -08:00
Kelly Brazil
3f13c70dfa formatting 2022-11-21 12:12:16 -08:00
Kelly Brazil
26f8803b23 add support for unparsable lines 2022-11-21 12:09:19 -08:00
Kelly Brazil
60f1e79b2f fix clf request string parsing and add tests 2022-11-21 11:00:58 -08:00
Kelly Brazil
5ab2ebe45a add CLF timestamp support 2022-11-21 09:27:37 -08:00
Kelly Brazil
9c8fe80d6d add more processing and timestamp 2022-11-21 09:27:21 -08:00
Kelly Brazil
1e7e22330f doc update 2022-11-20 20:45:22 -08:00
Kelly Brazil
7244868fbd initial common log format parser 2022-11-20 20:43:49 -08:00
Kelly Brazil
86ed39ecdd tighten up efi split 2022-11-18 16:19:55 -08:00
Kelly Brazil
94d87b726f add efi partition split 2022-11-18 14:20:18 -08:00
Kelly Brazil
0984a1ec26 fix git-log tests and docs 2022-11-18 13:54:59 -08:00
Kelly Brazil
de5da060ce Merge pull request #322 from adamwolf/git-log-blank-author
Fix git log parsing with empty name or email
2022-11-18 13:18:06 -06:00
Kelly Brazil
592435572c Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev
add in PR 323
2022-11-18 11:11:57 -08:00
Kelly Brazil
3172a18a46 Merge pull request #323 from kianmeng/fix-typos
Fix typos
2022-11-18 13:05:36 -06:00
Kelly Brazil
7f1c57b89c version bump 2022-11-17 13:39:59 -06:00
Kian-Meng Ang
39555a48b5 Fix typos
Found via `codespell -S ./tests/fixtures -L
chage,ro,ist,ans,unx,respons,technik`
2022-11-16 10:01:58 +08:00
Adam Wolf
e4cdfa13ca Fix git log parsing with empty name or email
Sometimes, folks leave their name or email blank in on their
git commits.  Previously, a blank name crashed the git log
parser.
2022-11-11 13:33:01 -06:00
Kelly Brazil
cb4011bc03 formatting 2022-11-08 14:23:32 -08:00
550 changed files with 26848 additions and 1278 deletions

View File

@@ -13,8 +13,8 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
os: [macos-latest, ubuntu-20.04, windows-latest]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v3

View File

@@ -1,5 +1,93 @@
jc changelog
20230621 v1.23.3
- Add `lsattr` command parser
- Add `srt` file parser
- Add `veracrypt` command parser
- Add X509 Certificate Request file parser
- Enhance X509 Certificate parser to allow non-compliant email addresses with a warning
- Enhance `dig` command parser to support the `+nsid` option
- Enhance `last` and `lastb` command parser to support the `-x` option
- Enhance `route` command parser to add Windows support
- Enhnace `netstat` command parser to add Windows support
- Enhance `ss` command parser to support extended options
- Enhance the compatibility warning message
- Fix `bluetoothctl` command parser for some mouse devices
- Fix `certbot` command parser to be more robust with different line endings
- Fix `ping` command parsers for output with missing hostname
- Fix `stat` command parser for older versions that may not contain all fields
- Fix deprecated option in `setup.cfg`
20230429 v1.23.2
- Add `bluetoothctl` command parser
- Add `certbot` command parser for `certificates` and `show_account` options
- Fix `acpi` command parser for "Not charging" battery status lines
- Fix `iwconfig` command parser for SSIDs with dashes in the name
- Fix `crontab` command parsers for incorrect variable parsing in some cases
- Fix `git-log` and `git-log-s` command parsers for incorrect insertion/deletion parsing
- Fix `ufw-appinfo` command parser for parsing errors on multiline description fields
- Fix pytest warnings
20230323 v1.23.1
- Fix `zpool-status` command parser for lines that start with tab
- Fix `timedatectl` command parser when RTC set to local
- Fix to ensure `py.typed` file is included in the package wheel
- Fix `lsusb` command parser to support CDC MBIM and CDC MBIM Extended fields
- Add support for the `timesync-status` for the `timedatectl` command parser
- Fix to ignore non-parser-plugins in the parser plugin directory
20230227 v1.23.0
- Add input slicing as a `jc` command-line option
- Add `ssh` configuration file parser
- Add `ver` Version string parser
- Add `zpool iostat` command parser
- Add `zpool status` command parser
- Fix `acpi` command parser for "will never fully discharge" battery state
- Fix `crontab` and `crontab-u` command and file parsers for cases where only
shortcut schedule items exist
- Fix `ifconfig` command parser for older-style linux output
- Fix `xrandr` command parser for proper `is_current` output
- Fix `xrandr` command parser for infinite loop with some device configurations
- Add `reflection` key to `xrandr` parser schema
- Add display model info from EDID to `xrandr` parser
- Add `MPX-specific VMA` support for VM Flags in `/proc/<pid>/smaps` parser
20230111 v1.22.5
- Add TOML file parser
- Add INI with duplicate key support file parser
- Add AIX support for the `arp` command parser
- Add AIX support for the `mount` command parser
- Fix `lsusb` command parser when extra hub port status information is output
- Refactor `lsusb` command parser for more code reuse
- Fix INI file parser to include top-level values with no section header
- Fix INI file parser to not specially handle the [DEFAULT] section
- Fix INI file and Key/Value parsers to only remove one quotation mark from the
beginning and end of values.
- Update copyright dates
20221230 v1.22.4
- Add `iwconfig` command parser
- Add NeXTSTEP format support to the PLIST file parser
- Fix `proc` parser magic signature detection for `/proc/pid/stat` hacks
- Fix `x509-cert` parser for string serial numbers
- Add category tags to parser metadata: generic, standard, file, string, binary, command
- Add "list parsers by category" view to help
- Fix python 3.6-related issues
- Add python 3.6 to automated tests
20221216 v1.22.3
- Add Common Log Format and Combined Log Format file parser (standard and streaming)
- Add PostgreSQL password file parser
- Add openvpn-status.log file parser
- Add `cbt` command parser (Google Big Table)
- Enhance `ifconfig` parser with interface lane information on BSD
- Enhance `ifconfig` parser with additional IPv6 `scope_id` info for BSD
- Fix `ifconfig` parser to capture some IPv6 addresses missed on BSD
- Fix `git-log` and `git-log-s` parsers for failure on empty author name
- Update `os-prober` parser with split EFI partition fields
- Add ISO string attribute (`.iso`) to `jc.utils.timestamp()`
- Fix several documentation typos
20221107 v1.22.2
- add `sshd_conf` parser for `sshd` configuration files and `sshd -T` output
- add `findmnt` command parser
@@ -581,7 +669,7 @@ jc changelog
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)
- Options can now be condensed (e.g. -prq is equivalent to -p -r -q)
20200208 v1.7.2
- Include test fixtures in wheel and sdist

View File

@@ -1636,21 +1636,21 @@ cat example.ini | jc --ini -p
```
```json
{
"bitbucket.org": {
"ServeraLiveInterval": "45",
"DEFAULT": {
"ServerAliveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "yes",
"ForwardX11": "yes"
},
"bitbucket.org": {
"User": "hg"
},
"topsecret.server.com": {
"ServeraLiveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "no",
"Port": "50022"
"Port": "50022",
"ForwardX11": "no"
}
}
```
### iostat
```bash
@@ -4551,6 +4551,57 @@ cat entrust.pem | jc --x509-cert -p
}
]
```
### X.509 PEM and DER certificate request files
```bash
cat myserver.csr | jc --x509-csr -p
```
```json
[
{
"certification_request_info": {
"version": "v1",
"subject": {
"common_name": "myserver.for.example"
},
"subject_pk_info": {
"algorithm": {
"algorithm": "ec",
"parameters": "secp256r1"
},
"public_key": "04:40:33:c0:91:8f:e9:46:ea:d0:dc:d0:f9:63:2c:a4:35:1f:0f:54:c8:a9:9b:e3:9e:d4:f3:64:b8:60:cc:7f:39:75:dd:a7:61:31:02:7c:9e:89:c6:db:45:15:f2:5f:b0:65:29:0b:42:d2:6e:c2:ea:a6:23:bd:fc:65:e5:7d:4e"
},
"attributes": [
{
"type": "extension_request",
"values": [
[
{
"extn_id": "extended_key_usage",
"critical": false,
"extn_value": [
"server_auth"
]
},
{
"extn_id": "subject_alt_name",
"critical": false,
"extn_value": [
"myserver.for.example"
]
}
]
]
}
]
},
"signature_algorithm": {
"algorithm": "sha384_ecdsa",
"parameters": null
},
"signature": "30:45:02:20:77:ac:5b:51:bf:c5:f5:43:02:52:ae:66:8a:fe:95:98:98:98:a9:45:34:31:08:ff:2c:cc:92:d9:1c:70:28:74:02:21:00:97:79:7b:e7:45:18:76:cf:d7:3b:79:34:56:d2:69:b5:73:41:9b:8a:b7:ad:ec:80:23:c1:2f:64:da:e5:28:19"
}
]
```
### XML files
```bash
cat cd_catalog.xml

392
README.md
View File

@@ -3,13 +3,15 @@
> Check out the `jc` Python [package documentation](https://github.com/kellyjonbrazil/jc/tree/master/docs) for developers
> Try the `jc` [web demo](https://jc-web.onrender.com/)
> Try the `jc` [web demo](https://jc-web.onrender.com/) and [REST API](https://github.com/kellyjonbrazil/jc-restapi)
> JC is [now available](https://galaxy.ansible.com/community/general) as an
> `jc` is [now available](https://galaxy.ansible.com/community/general) as an
Ansible filter plugin in the `community.general` collection. See this
[blog post](https://blog.kellybrazil.com/2020/08/30/parsing-command-output-in-ansible-with-jc/)
for an example.
> Looking for something like `jc` but lower-level? Check out [regex2json](https://gitlab.com/tozd/regex2json).
# JC
JSON Convert
@@ -44,8 +46,8 @@ $ jc dig example.com | jq -r '.[].answer[].data'
93.184.216.34
```
`jc` can also be used as a python library. In this case the output will be
a python dictionary, a list of dictionaries, or even a
`jc` can also be used as a python library. In this case the returned value
will be a python dictionary, a list of dictionaries, or even a
[lazy iterable of dictionaries](#using-streaming-parsers-as-python-modules)
instead of JSON:
```python
@@ -133,9 +135,9 @@ on Github.
`jc` accepts piped input from `STDIN` and outputs a JSON representation of the
previous command's output to `STDOUT`.
```bash
COMMAND | jc [OPTIONS] PARSER
cat FILE | jc [OPTIONS] PARSER
echo STRING | jc [OPTIONS] PARSER
COMMAND | jc [SLICE] [OPTIONS] PARSER
cat FILE | jc [SLICE] [OPTIONS] PARSER
echo STRING | jc [SLICE] [OPTIONS] PARSER
```
Alternatively, the "magic" syntax can be used by prepending `jc` to the command
@@ -143,8 +145,8 @@ to be converted or in front of the absolute path for Proc files. Options can be
passed to `jc` immediately before the command or Proc file path is given.
(Note: command aliases and shell builtins are not supported)
```bash
jc [OPTIONS] COMMAND
jc [OPTIONS] /proc/<path-to-procfile>
jc [SLICE] [OPTIONS] COMMAND
jc [SLICE] [OPTIONS] /proc/<path-to-procfile>
```
The JSON output can be compact (default) or pretty formatted with the `-p`
@@ -154,135 +156,153 @@ option.
| Argument | Command or Filetype | Documentation |
|-------------------|---------------------------------------------------------|----------------------------------------------------------------------------|
| ` --acpi` | `acpi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi) |
| ` --airport` | `airport -I` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport) |
| ` --airport-s` | `airport -s` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s) |
| ` --arp` | `arp` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/arp) |
| ` --asciitable` | ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable) |
| ` --asciitable-m` | multi-line ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m) |
| ` --blkid` | `blkid` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid) |
| ` --cef` | CEF string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef) |
| ` --cef-s` | CEF string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef_s) |
| ` --chage` | `chage --list` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/chage) |
| ` --cksum` | `cksum` and `sum` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum) |
| ` --crontab` | `crontab` command and file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab) |
| ` --crontab-u` | `crontab` file parser with user support | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u) |
| ` --csv` | CSV file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/csv) |
| ` --csv-s` | CSV file streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s) |
| ` --date` | `date` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/date) |
| ` --datetime-iso` | ISO 8601 Datetime string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/datetime_iso) |
| ` --df` | `df` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/df) |
| ` --dig` | `dig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dig) |
| ` --dir` | `dir` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dir) |
| ` --dmidecode` | `dmidecode` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dmidecode) |
| ` --dpkg-l` | `dpkg -l` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dpkg_l) |
| ` --du` | `du` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/du) |
| `--acpi` | `acpi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi) |
| `--airport` | `airport -I` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport) |
| `--airport-s` | `airport -s` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s) |
| `--arp` | `arp` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/arp) |
| `--asciitable` | ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable) |
| `--asciitable-m` | multi-line ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m) |
| `--blkid` | `blkid` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid) |
| `--bluetoothctl` | `bluetoothctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/bluetoothctl) |
| `--cbt` | `cbt` (Google Bigtable) command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cbt) |
| `--cef` | CEF string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef) |
| `--cef-s` | CEF string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef_s) |
| `--certbot` | `certbot` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/certbot) |
| `--chage` | `chage --list` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/chage) |
| `--cksum` | `cksum` and `sum` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum) |
| `--clf` | Common and Combined Log Format file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/clf) |
| `--clf-s` | Common and Combined Log Format file streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/clf_s) |
| `--crontab` | `crontab` command and file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab) |
| `--crontab-u` | `crontab` file parser with user support | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u) |
| `--csv` | CSV file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/csv) |
| `--csv-s` | CSV file streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s) |
| `--date` | `date` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/date) |
| `--datetime-iso` | ISO 8601 Datetime string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/datetime_iso) |
| `--df` | `df` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/df) |
| `--dig` | `dig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dig) |
| `--dir` | `dir` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dir) |
| `--dmidecode` | `dmidecode` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dmidecode) |
| `--dpkg-l` | `dpkg -l` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/dpkg_l) |
| `--du` | `du` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/du) |
| `--email-address` | Email Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/email_address) |
| ` --env` | `env` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/env) |
| ` --file` | `file` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/file) |
| ` --findmnt` | `findmnt` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/findmnt) |
| ` --finger` | `finger` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/finger) |
| ` --free` | `free` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/free) |
| ` --fstab` | `/etc/fstab` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/fstab) |
| ` --git-log` | `git log` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log) |
| ` --git-log-s` | `git log` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log_s) |
| `--env` | `env` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/env) |
| `--file` | `file` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/file) |
| `--findmnt` | `findmnt` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/findmnt) |
| `--finger` | `finger` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/finger) |
| `--free` | `free` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/free) |
| `--fstab` | `/etc/fstab` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/fstab) |
| `--git-log` | `git log` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log) |
| `--git-log-s` | `git log` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log_s) |
| `--git-ls-remote` | `git ls-remote` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/git_ls_remote) |
| ` --gpg` | `gpg --with-colons` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/gpg) |
| ` --group` | `/etc/group` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/group) |
| ` --gshadow` | `/etc/gshadow` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/gshadow) |
| ` --hash` | `hash` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hash) |
| ` --hashsum` | hashsum command parser (`md5sum`, `shasum`, etc.) | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hashsum) |
| ` --hciconfig` | `hciconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hciconfig) |
| ` --history` | `history` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/history) |
| ` --hosts` | `/etc/hosts` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hosts) |
| ` --id` | `id` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/id) |
| ` --ifconfig` | `ifconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig) |
| ` --ini` | INI file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ini) |
| ` --iostat` | `iostat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat) |
| ` --iostat-s` | `iostat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s) |
| ` --ip-address` | IPv4 and IPv6 Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ip_address) |
| ` --iptables` | `iptables` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables) |
| ` --iw-scan` | `iw dev [device] scan` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan) |
| ` --jar-manifest` | Java MANIFEST.MF file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) |
| ` --jobs` | `jobs` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs) |
| ` --jwt` | JWT string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jwt) |
| ` --kv` | Key/Value file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/kv) |
| ` --last` | `last` and `lastb` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/last) |
| ` --ls` | `ls` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls) |
| ` --ls-s` | `ls` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s) |
| ` --lsblk` | `lsblk` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk) |
| ` --lsmod` | `lsmod` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod) |
| ` --lsof` | `lsof` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof) |
| ` --lspci` | `lspci -mmv` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lspci) |
| ` --lsusb` | `lsusb` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb) |
| ` --m3u` | M3U and M3U8 file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/m3u) |
| ` --mdadm` | `mdadm` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mdadm) |
| ` --mount` | `mount` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mount) |
| ` --mpstat` | `mpstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat) |
| ` --mpstat-s` | `mpstat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s) |
| ` --netstat` | `netstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat) |
| ` --nmcli` | `nmcli` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli) |
| ` --ntpq` | `ntpq -p` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq) |
| ` --os-prober` | `os-prober` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/os_prober) |
| ` --passwd` | `/etc/passwd` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd) |
| ` --pci-ids` | `pci.ids` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pci_ids) |
| ` --pidstat` | `pidstat -H` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat) |
| ` --pidstat-s` | `pidstat -H` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat_s) |
| ` --ping` | `ping` and `ping6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ping) |
| ` --ping-s` | `ping` and `ping6` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ping_s) |
| ` --pip-list` | `pip list` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_list) |
| ` --pip-show` | `pip show` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_show) |
| ` --plist` | PLIST file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/plist) |
| ` --postconf` | `postconf -M` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/postconf) |
| ` --proc` | `/proc/` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/proc) |
| ` --ps` | `ps` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ps) |
| ` --route` | `route` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/route) |
| ` --rpm-qi` | `rpm -qi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi) |
| ` --rsync` | `rsync` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync) |
| ` --rsync-s` | `rsync` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s) |
| ` --semver` | Semantic Version string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/semver) |
| ` --sfdisk` | `sfdisk` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sfdisk) |
| ` --shadow` | `/etc/shadow` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/shadow) |
| ` --ss` | `ss` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ss) |
| ` --sshd-conf` | sshd config file and `sshd -T` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sshd_conf) |
| ` --stat` | `stat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat) |
| ` --stat-s` | `stat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s) |
| ` --sysctl` | `sysctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl) |
| ` --syslog` | Syslog RFC 5424 string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog) |
| ` --syslog-s` | Syslog RFC 5424 string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_s) |
| ` --syslog-bsd` | Syslog RFC 3164 string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_bsd) |
| ` --syslog-bsd-s` | Syslog RFC 3164 string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_bsd_s) |
| ` --systemctl` | `systemctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl) |
| ` --systemctl-lj` | `systemctl list-jobs` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj) |
| ` --systemctl-ls` | `systemctl list-sockets` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls) |
| `--gpg` | `gpg --with-colons` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/gpg) |
| `--group` | `/etc/group` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/group) |
| `--gshadow` | `/etc/gshadow` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/gshadow) |
| `--hash` | `hash` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hash) |
| `--hashsum` | hashsum command parser (`md5sum`, `shasum`, etc.) | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hashsum) |
| `--hciconfig` | `hciconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hciconfig) |
| `--history` | `history` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/history) |
| `--hosts` | `/etc/hosts` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hosts) |
| `--id` | `id` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/id) |
| `--ifconfig` | `ifconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig) |
| `--ini` | INI file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ini) |
| `--ini-dup` | INI with duplicate key file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ini_dup) |
| `--iostat` | `iostat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat) |
| `--iostat-s` | `iostat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s) |
| `--ip-address` | IPv4 and IPv6 Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ip_address) |
| `--iptables` | `iptables` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables) |
| `--iw-scan` | `iw dev [device] scan` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan) |
| `--iwconfig` | `iwconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iwconfig) |
| `--jar-manifest` | Java MANIFEST.MF file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) |
| `--jobs` | `jobs` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs) |
| `--jwt` | JWT string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jwt) |
| `--kv` | Key/Value file and string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/kv) |
| `--last` | `last` and `lastb` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/last) |
| `--ls` | `ls` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls) |
| `--ls-s` | `ls` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s) |
| `--lsattr` | `lsattr` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsattr) |
| `--lsblk` | `lsblk` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk) |
| `--lsmod` | `lsmod` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod) |
| `--lsof` | `lsof` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof) |
| `--lspci` | `lspci -mmv` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lspci) |
| `--lsusb` | `lsusb` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb) |
| `--m3u` | M3U and M3U8 file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/m3u) |
| `--mdadm` | `mdadm` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mdadm) |
| `--mount` | `mount` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mount) |
| `--mpstat` | `mpstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat) |
| `--mpstat-s` | `mpstat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s) |
| `--netstat` | `netstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat) |
| `--nmcli` | `nmcli` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli) |
| `--ntpq` | `ntpq -p` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq) |
| `--openvpn` | openvpn-status.log file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/openvpn) |
| `--os-prober` | `os-prober` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/os_prober) |
| `--passwd` | `/etc/passwd` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd) |
| `--pci-ids` | `pci.ids` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pci_ids) |
| `--pgpass` | PostgreSQL password file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pgpass) |
| `--pidstat` | `pidstat -H` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat) |
| `--pidstat-s` | `pidstat -H` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat_s) |
| `--ping` | `ping` and `ping6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ping) |
| `--ping-s` | `ping` and `ping6` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ping_s) |
| `--pip-list` | `pip list` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_list) |
| `--pip-show` | `pip show` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_show) |
| `--plist` | PLIST file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/plist) |
| `--postconf` | `postconf -M` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/postconf) |
| `--proc` | `/proc/` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/proc) |
| `--ps` | `ps` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ps) |
| `--route` | `route` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/route) |
| `--rpm-qi` | `rpm -qi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi) |
| `--rsync` | `rsync` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync) |
| `--rsync-s` | `rsync` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s) |
| `--semver` | Semantic Version string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/semver) |
| `--sfdisk` | `sfdisk` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sfdisk) |
| `--shadow` | `/etc/shadow` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/shadow) |
| `--srt` | SRT file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/srt) |
| `--ss` | `ss` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ss) |
| `--ssh-conf` | `ssh` config file and `ssh -G` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ssh_conf) |
| `--sshd-conf` | `sshd` config file and `sshd -T` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sshd_conf) |
| `--stat` | `stat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat) |
| `--stat-s` | `stat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s) |
| `--sysctl` | `sysctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl) |
| `--syslog` | Syslog RFC 5424 string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog) |
| `--syslog-s` | Syslog RFC 5424 string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_s) |
| `--syslog-bsd` | Syslog RFC 3164 string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_bsd) |
| `--syslog-bsd-s` | Syslog RFC 3164 string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_bsd_s) |
| `--systemctl` | `systemctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl) |
| `--systemctl-lj` | `systemctl list-jobs` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj) |
| `--systemctl-ls` | `systemctl list-sockets` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls) |
| `--systemctl-luf` | `systemctl list-unit-files` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_luf) |
| ` --systeminfo` | `systeminfo` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo) |
| ` --time` | `/usr/bin/time` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/time) |
| ` --timedatectl` | `timedatectl status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl) |
| ` --timestamp` | Unix Epoch Timestamp string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timestamp) |
| ` --top` | `top -b` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top) |
| ` --top-s` | `top -b` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
| ` --tracepath` | `tracepath` and `tracepath6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
| ` --traceroute` | `traceroute` and `traceroute6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute) |
| ` --udevadm` | `udevadm info` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/udevadm) |
| ` --ufw` | `ufw status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw) |
| ` --ufw-appinfo` | `ufw app info [application]` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw_appinfo) |
| ` --uname` | `uname -a` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/uname) |
| `--systeminfo` | `systeminfo` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo) |
| `--time` | `/usr/bin/time` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/time) |
| `--timedatectl` | `timedatectl status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl) |
| `--timestamp` | Unix Epoch Timestamp string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timestamp) |
| `--toml` | TOML file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/toml) |
| `--top` | `top -b` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top) |
| `--top-s` | `top -b` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
| `--tracepath` | `tracepath` and `tracepath6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
| `--traceroute` | `traceroute` and `traceroute6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute) |
| `--udevadm` | `udevadm info` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/udevadm) |
| `--ufw` | `ufw status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw) |
| `--ufw-appinfo` | `ufw app info [application]` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw_appinfo) |
| `--uname` | `uname -a` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/uname) |
| `--update-alt-gs` | `update-alternatives --get-selections` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_gs) |
| ` --update-alt-q` | `update-alternatives --query` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_q) |
| ` --upower` | `upower` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/upower) |
| ` --uptime` | `uptime` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/uptime) |
| ` --url` | URL string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/url) |
| ` --vmstat` | `vmstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat) |
| ` --vmstat-s` | `vmstat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat_s) |
| ` --w` | `w` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/w) |
| ` --wc` | `wc` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/wc) |
| ` --who` | `who` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/who) |
| ` --x509-cert` | X.509 PEM and DER certificate file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/x509_cert) |
| ` --xml` | XML file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/xml) |
| ` --xrandr` | `xrandr` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/xrandr) |
| ` --yaml` | YAML file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/yaml) |
| ` --zipinfo` | `zipinfo` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/zipinfo) |
| `--update-alt-q` | `update-alternatives --query` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_q) |
| `--upower` | `upower` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/upower) |
| `--uptime` | `uptime` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/uptime) |
| `--url` | URL string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/url) |
| `--ver` | Version string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ver) |
| `--veracrypt` | `veracrypt` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/veracrypt) |
| `--vmstat` | `vmstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat) |
| `--vmstat-s` | `vmstat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat_s) |
| `--w` | `w` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/w) |
| `--wc` | `wc` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/wc) |
| `--who` | `who` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/who) |
| `--x509-cert` | X.509 PEM and DER certificate file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/x509_cert) |
| `--x509-csr` | X.509 PEM and DER certificate request file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/x509_csr) |
| `--xml` | XML file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/xml) |
| `--xrandr` | `xrandr` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/xrandr) |
| `--yaml` | YAML file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/yaml) |
| `--zipinfo` | `zipinfo` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/zipinfo) |
| `--zpool-iostat` | `zpool iostat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/zpool_iostat) |
| `--zpool-status` | `zpool status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/zpool_status) |
### Options
@@ -303,6 +323,54 @@ option.
| `-B` | `--bash-comp` | Generate Bash shell completion script ([more info](https://github.com/kellyjonbrazil/jc/wiki/Shell-Completions)) |
| `-Z` | `--zsh-comp` | Generate Zsh shell completion script ([more info](https://github.com/kellyjonbrazil/jc/wiki/Shell-Completions)) |
### Slice
Line slicing is supported using the `START:STOP` syntax similar to Python
slicing. This allows you to skip lines at the beginning and/or end of the
`STDIN` input you would like `jc` to convert.
`START` and `STOP` can be positive or negative integers or blank and allow
you to specify how many lines to skip and how many lines to process.
Positive and blank slices are the most memory efficient. Any negative
integers in the slice will use more memory.
For example, to skip the first and last line of the following text, you
could express the slice in a couple ways:
```bash
$ cat table.txt
### We want to skip this header ###
col1 col2
foo 1
bar 2
### We want to skip this footer ###
$ cat table.txt | jc 1:-1 --asciitable
[{"col1":"foo","col2":"1"},{"col1":"bar","col2":"2"}]
$ cat table.txt | jc 1:4 --asciitable
[{"col1":"foo","col2":"1"},{"col1":"bar","col2":"2"}]
```
In this example `1:-1` and `1:4` line slices provide the same output.
When using positive integers the index location of `STOP` is non-inclusive.
Positive slices count from the first line of the input toward the end
starting at `0` as the first line. Negative slices count from the last line
toward the beginning starting at `-1` as the last line. This is also the way
[Python's slicing](https://stackoverflow.com/questions/509211/understanding-slicing)
feature works.
Here is a breakdown of line slice options:
| Slice Notation | Input Lines Processed |
|----------------|--------------------------------------------------------------|
| `START:STOP` | lines `START` through `STOP - 1` |
| `START:` | lines `START` through the rest of the output |
| `:STOP` | lines from the beginning through `STOP - 1` |
| `-START:STOP` | `START` lines from the end through `STOP - 1` |
| `START:-STOP` | lines `START` through `STOP` lines from the end |
| `-START:-STOP` | `START` lines from the end through `STOP` lines from the end |
| `-START:` | `START` lines from the end through the rest of the output |
| `:-STOP` | lines from the beginning through `STOP` lines from the end |
| `:` | all lines |
### Exit Codes
Any fatal errors within `jc` will generate an exit code of `100`, otherwise the
exit code will be `0`.
@@ -390,7 +458,7 @@ option.
### Streaming Parsers
Most parsers load all of the data from `STDIN`, parse it, then output the entire
JSON document serially. There are some streaming parsers (e.g. `ls-s` and
`ping-s`) that immediately start processing and outputing the data line-by-line
`ping-s`) that immediately start processing and outputting the data line-by-line
as [JSON Lines](https://jsonlines.org/) (aka [NDJSON](http://ndjson.org/)) while
it is being received from `STDIN`. This can significantly reduce the amount of
memory required to parse large amounts of command output (e.g. `ls -lR /`) and
@@ -473,20 +541,22 @@ for item in result:
print(item["filename"])
```
### Custom Parsers
Custom local parser plugins may be placed in a `jc/jcparsers` folder in your
local **"App data directory"**:
### Parser Plugins
Parser plugins may be placed in a `jc/jcparsers` folder in your local
**"App data directory"**:
- Linux/unix: `$HOME/.local/share/jc/jcparsers`
- macOS: `$HOME/Library/Application Support/jc/jcparsers`
- Windows: `$LOCALAPPDATA\jc\jc\jcparsers`
Local parser plugins are standard python module files. Use the
Parser plugins are standard python module files. Use the
[`jc/parsers/foo.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo.py)
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py)
parser as a template and simply place a `.py` file in the `jcparsers` subfolder.
Any dependencies can be placed in the `jc` folder above `jcparsers` and can
be imported in the parser code.
Local plugin filenames must be valid python module names and therefore must
Parser plugin filenames must be valid python module names and therefore must
start with a letter and consist entirely of alphanumerics and underscores.
Local plugins may override default parsers.
@@ -544,7 +614,7 @@ they are run on an unsupported platform. To see all parser information,
including compatibility, run `jc -ap`.
You may still use a parser on an unsupported platform - for example, you may
want to parse a file with linux `lsof` output on an macOS or Windows laptop. In
want to parse a file with linux `lsof` output on a macOS or Windows laptop. In
that case you can suppress the warning message with the `-q` cli option or the
`quiet=True` function parameter in `parse()`:
@@ -750,37 +820,31 @@ ifconfig | jc -p --ifconfig # or: jc -p ifconfig
cat example.ini
```
```
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
foo = fiz
bar = buz
[bitbucket.org]
User = hg
[section1]
fruit = apple
color = blue
[topsecret.server.com]
Port = 50022
ForwardX11 = no
[section2]
fruit = pear
color = green
```
```bash
cat example.ini | jc -p --ini
```
```json
{
"bitbucket.org": {
"ServeraLiveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "yes",
"User": "hg"
"foo": "fiz",
"bar": "buz",
"section1": {
"fruit": "apple",
"color": "blue"
},
"topsecret.server.com": {
"ServeraLiveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "no",
"Port": "50022"
"section2": {
"fruit": "pear",
"color": "green"
}
}
```
@@ -1236,4 +1300,4 @@ cat istio.yaml | jc -p --yaml
]
```
© 2019-2022 Kelly Brazil
© 2019-2023 Kelly Brazil

View File

@@ -3,8 +3,8 @@ _jc()
local cur prev words cword jc_commands jc_parsers jc_options \
jc_about_options jc_about_mod_options jc_help_options jc_special_options
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cef --cef-s --chage --cksum --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --ip-address --iptables --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --os-prober --passwd --pci-ids --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --ss --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_about_options=(--about -a)
jc_about_mod_options=(--pretty -p --yaml-out -y --monochrome -m --force-color -C)

View File

@@ -9,12 +9,15 @@ _jc() {
jc_help_options jc_help_options_describe \
jc_special_options jc_special_options_describe
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool)
jc_commands_describe=(
'acpi:run "acpi" command with magic syntax.'
'airport:run "airport" command with magic syntax.'
'arp:run "arp" command with magic syntax.'
'blkid:run "blkid" command with magic syntax.'
'bluetoothctl:run "bluetoothctl" command with magic syntax.'
'cbt:run "cbt" command with magic syntax.'
'certbot:run "certbot" command with magic syntax.'
'chage:run "chage" command with magic syntax.'
'cksum:run "cksum" command with magic syntax.'
'crontab:run "crontab" command with magic syntax.'
@@ -37,10 +40,12 @@ _jc() {
'iostat:run "iostat" command with magic syntax.'
'iptables:run "iptables" command with magic syntax.'
'iw:run "iw" command with magic syntax.'
'iwconfig:run "iwconfig" command with magic syntax.'
'jobs:run "jobs" command with magic syntax.'
'last:run "last" command with magic syntax.'
'lastb:run "lastb" command with magic syntax.'
'ls:run "ls" command with magic syntax.'
'lsattr:run "lsattr" command with magic syntax.'
'lsblk:run "lsblk" command with magic syntax.'
'lsmod:run "lsmod" command with magic syntax.'
'lsof:run "lsof" command with magic syntax.'
@@ -74,6 +79,7 @@ _jc() {
'sha512sum:run "sha512sum" command with magic syntax.'
'shasum:run "shasum" command with magic syntax.'
'ss:run "ss" command with magic syntax.'
'ssh:run "ssh" command with magic syntax.'
'sshd:run "sshd" command with magic syntax.'
'stat:run "stat" command with magic syntax.'
'sum:run "sum" command with magic syntax.'
@@ -93,14 +99,16 @@ _jc() {
'upower:run "upower" command with magic syntax.'
'uptime:run "uptime" command with magic syntax.'
'vdir:run "vdir" command with magic syntax.'
'veracrypt:run "veracrypt" command with magic syntax.'
'vmstat:run "vmstat" command with magic syntax.'
'w:run "w" command with magic syntax.'
'wc:run "wc" command with magic syntax.'
'who:run "who" command with magic syntax.'
'xrandr:run "xrandr" command with magic syntax.'
'zipinfo:run "zipinfo" command with magic syntax.'
'zpool:run "zpool" command with magic syntax.'
)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cef --cef-s --chage --cksum --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --ip-address --iptables --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --os-prober --passwd --pci-ids --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --ss --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_parsers_describe=(
'--acpi:`acpi` command parser'
'--airport:`airport -I` command parser'
@@ -109,10 +117,15 @@ _jc() {
'--asciitable:ASCII and Unicode table parser'
'--asciitable-m:multi-line ASCII and Unicode table parser'
'--blkid:`blkid` command parser'
'--bluetoothctl:`bluetoothctl` command parser'
'--cbt:`cbt` (Google Bigtable) command parser'
'--cef:CEF string parser'
'--cef-s:CEF string streaming parser'
'--certbot:`certbot` command parser'
'--chage:`chage --list` command parser'
'--cksum:`cksum` and `sum` command parser'
'--clf:Common and Combined Log Format file parser'
'--clf-s:Common and Combined Log Format file streaming parser'
'--crontab:`crontab` command and file parser'
'--crontab-u:`crontab` file parser with user support'
'--csv:CSV file parser'
@@ -146,18 +159,21 @@ _jc() {
'--id:`id` command parser'
'--ifconfig:`ifconfig` command parser'
'--ini:INI file parser'
'--ini-dup:INI with duplicate key file parser'
'--iostat:`iostat` command parser'
'--iostat-s:`iostat` command streaming parser'
'--ip-address:IPv4 and IPv6 Address string parser'
'--iptables:`iptables` command parser'
'--iw-scan:`iw dev [device] scan` command parser'
'--iwconfig:`iwconfig` command parser'
'--jar-manifest:Java MANIFEST.MF file parser'
'--jobs:`jobs` command parser'
'--jwt:JWT string parser'
'--kv:Key/Value file parser'
'--kv:Key/Value file and string parser'
'--last:`last` and `lastb` command parser'
'--ls:`ls` command parser'
'--ls-s:`ls` command streaming parser'
'--lsattr:`lsattr` command parser'
'--lsblk:`lsblk` command parser'
'--lsmod:`lsmod` command parser'
'--lsof:`lsof` command parser'
@@ -171,9 +187,11 @@ _jc() {
'--netstat:`netstat` command parser'
'--nmcli:`nmcli` command parser'
'--ntpq:`ntpq -p` command parser'
'--openvpn:openvpn-status.log file parser'
'--os-prober:`os-prober` command parser'
'--passwd:`/etc/passwd` file parser'
'--pci-ids:`pci.ids` file parser'
'--pgpass:PostgreSQL password file parser'
'--pidstat:`pidstat -H` command parser'
'--pidstat-s:`pidstat -H` command streaming parser'
'--ping:`ping` and `ping6` command parser'
@@ -240,8 +258,10 @@ _jc() {
'--semver:Semantic Version string parser'
'--sfdisk:`sfdisk` command parser'
'--shadow:`/etc/shadow` file parser'
'--srt:SRT file parser'
'--ss:`ss` command parser'
'--sshd-conf:sshd config file and `sshd -T` command parser'
'--ssh-conf:`ssh` config file and `ssh -G` command parser'
'--sshd-conf:`sshd` config file and `sshd -T` command parser'
'--stat:`stat` command parser'
'--stat-s:`stat` command streaming parser'
'--sysctl:`sysctl` command parser'
@@ -257,6 +277,7 @@ _jc() {
'--time:`/usr/bin/time` command parser'
'--timedatectl:`timedatectl status` command parser'
'--timestamp:Unix Epoch Timestamp string parser'
'--toml:TOML file parser'
'--top:`top -b` command parser'
'--top-s:`top -b` command streaming parser'
'--tracepath:`tracepath` and `tracepath6` command parser'
@@ -270,21 +291,26 @@ _jc() {
'--upower:`upower` command parser'
'--uptime:`uptime` command parser'
'--url:URL string parser'
'--ver:Version string parser'
'--veracrypt:`veracrypt` command parser'
'--vmstat:`vmstat` command parser'
'--vmstat-s:`vmstat` command streaming parser'
'--w:`w` command parser'
'--wc:`wc` command parser'
'--who:`who` command parser'
'--x509-cert:X.509 PEM and DER certificate file parser'
'--x509-csr:X.509 PEM and DER certificate request file parser'
'--xml:XML file parser'
'--xrandr:`xrandr` command parser'
'--yaml:YAML file parser'
'--zipinfo:`zipinfo` command parser'
'--zpool-iostat:`zpool iostat` command parser'
'--zpool-status:`zpool status` command parser'
)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_options_describe=(
'--force-color:force color output even when using pipes (overrides -m)'
'-C:force color output even when using pipes (overrides -m)'
'--force-color:force color output (overrides -m)'
'-C:force color output (overrides -m)'
'--debug:debug (double for verbose debug)'
'-d:debug (double for verbose debug)'
'--monochrome:monochrome output'
@@ -315,8 +341,8 @@ _jc() {
'-y:YAML output'
'--monochrome:monochrome output'
'-m:monochrome output'
'--force-color:force color output even when using pipes (overrides -m)'
'-C:force color output even when using pipes (overrides -m)'
'--force-color:force color output (overrides -m)'
'-C:force color output (overrides -m)'
)
jc_help_options=(--help -h)
jc_help_options_describe=(

View File

@@ -26,7 +26,7 @@ def parse(
data: Union[str, bytes, Iterable[str]],
quiet: bool = False,
raw: bool = False,
ignore_exceptions: bool = None,
ignore_exceptions: Optional[bool] = None,
**kwargs
) -> Union[JSONDictType, List[JSONDictType], Iterator[JSONDictType]]
```

View File

@@ -250,4 +250,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -140,4 +140,4 @@ Returns:
### Parser Information
Compatibility: linux, aix, freebsd, darwin
Version 1.11 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.12 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -0,0 +1,133 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.bluetoothctl"></a>
# jc.parsers.bluetoothctl
jc - JSON Convert `bluetoothctl` command output parser
Supports the following `bluetoothctl` subcommands:
- `bluetoothctl list`
- `bluetoothctl show`
- `bluetoothctl show <ctrl>`
- `bluetoothctl devices`
- `bluetoothctl info <dev>`
Usage (cli):
$ bluetoothctl info <dev> | jc --bluetoothctl
or
$ jc bluetoothctl info <dev>
Usage (module):
import jc
result = jc.parse('bluetoothctl', bluetoothctl_command_output)
Schema:
Because bluetoothctl is handling two main entities, controllers and devices,
the schema is shared between them. Most of the fields are common between
a controller and a device but there might be fields corresponding to one entity.
Controller:
[
{
"name": string,
"is_default": boolean,
"is_public": boolean,
"is_random": boolean,
"address": string,
"alias": string,
"class": string,
"powered": string,
"discoverable": string,
"discoverable_timeout": string,
"pairable": string,
"modalias": string,
"discovering": string,
"uuids": array
}
]
Device:
[
{
"name": string,
"is_public": boolean,
"is_random": boolean,
"address": string,
"alias": string,
"appearance": string,
"class": string,
"icon": string,
"paired": string,
"bonded": string,
"trusted": string,
"blocked": string,
"connected": string,
"legacy_pairing": string,
"rssi": int,
"txpower": int,
"uuids": array,
"modalias": string
}
]
Examples:
$ bluetoothctl info EB:06:EF:62:B3:19 | jc --bluetoothctl -p
[
{
"address": "22:06:33:62:B3:19",
"is_public": true,
"name": "TaoTronics TT-BH336",
"alias": "TaoTronics TT-BH336",
"class": "0x00240455",
"icon": "audio-headset",
"paired": "no",
"bonded": "no",
"trusted": "no",
"blocked": "no",
"connected": "no",
"legacy_pairing": "no",
"uuids": [
"Advanced Audio Distribu.. (0000120d-0000-1000-8000-00805f9b34fb)",
"Audio Sink (0000130b-0000-1000-8000-00805f9b34fb)",
"A/V Remote Control (0000140e-0000-1000-8000-00805f9b34fb)",
"A/V Remote Control Cont.. (0000150f-0000-1000-8000-00805f9b34fb)",
"Handsfree (0000161e-0000-1000-8000-00805f9b34fb)",
"Headset (00001708-0000-1000-8000-00805f9b34fb)",
"Headset HS (00001831-0000-1000-8000-00805f9b34fb)"
],
"rssi": -52,
"txpower": 4
}
]
<a id="jc.parsers.bluetoothctl.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.1 by Jake Ob (iakopap at gmail.com)

125
docs/parsers/cbt.md Normal file
View File

@@ -0,0 +1,125 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.cbt"></a>
# jc.parsers.cbt
jc - JSON Convert `cbt` command output parser (Google Bigtable)
Parses the human-, but not machine-, friendly output of the cbt command (for
Google's Bigtable).
No effort is made to convert the data types of the values in the cells.
The `timestamp_epoch` calculated timestamp field is naive. (i.e. based on
the local time of the system the parser is run on)
The `timestamp_epoch_utc` calculated timestamp field is timezone-aware and
is only available if the timestamp has a UTC timezone.
The `timestamp_iso` calculated timestamp field will only include UTC
timezone information if the timestamp has a UTC timezone.
Raw output contains all cells for each column (including timestamps), while
the normal output contains only the latest value for each column.
Usage (cli):
$ cbt | jc --cbt
or
$ jc cbt
Usage (module):
import jc
result = jc.parse('cbt', cbt_command_output)
Schema:
[
{
"key": string,
"cells": {
<string>: { # column family
<string>: string # column: value
}
}
}
]
Schema (raw):
[
{
"key": string,
"cells": [
{
"column_family": string,
"column": string,
"value": string,
"timestamp_iso": string,
"timestamp_epoch": integer,
"timestamp_epoch_utc": integer
}
]
}
]
Examples:
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p
[
{
"key": "foo",
"cells": {
"foo": {
"bar": "baz"
}
}
}
]
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p -r
[
{
"key": "foo",
"cells": [
{
"column_family": "foo",
"column": "bar",
"value": "baz1",
"timestamp_iso": "1970-01-01T01:00:00",
"timestamp_epoch": 32400,
"timestamp_epoch_utc": null
}
]
}
]
<a id="jc.parsers.cbt.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Andreas Weiden (andreas.weiden@gmail.com)

161
docs/parsers/certbot.md Normal file
View File

@@ -0,0 +1,161 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.certbot"></a>
# jc.parsers.certbot
jc - JSON Convert `certbot` command output parser
Supports the following `certbot` commands:
- `certbot show_account`
- `certbot certificates`
Verbose options are not supported.
Usage (cli):
$ certbot show_account | jc --certbot
$ certbot certificates | jc --certbot
or
$ jc certbot show_account
$ jc certbot certificates
Usage (module):
import jc
result = jc.parse('certbot', certbot_command_output)
Schema:
{
"certificates": [
{
"name": string,
"serial_number": string,
"key_type": string,
"domains": [
string
],
"expiration_date": string,
"expiration_date_epoch": integer,
"expiration_date_epoch_utc": integer,
"expiration_date_iso": string,
"validity": string,
"certificate_path": string,
"private_key_path": string
}
],
"account": {
"server": string,
"url": string,
"email": string
}
}
Examples:
$ certbot certificates | jc --certbot -p
{
"certificates": [
{
"name": "example.com",
"serial_number": "3f7axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"key_type": "RSA",
"domains": [
"example.com",
"www.example.com"
],
"expiration_date": "2023-05-11 01:33:10+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.com/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.com/priv.pem",
"expiration_date_epoch": 1683793990,
"expiration_date_epoch_utc": 1683768790,
"expiration_date_iso": "2023-05-11T01:33:10+00:00"
},
{
"name": "example.org",
"serial_number": "3bcyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"key_type": "RSA",
"domains": [
"example.org",
"www.example.org"
],
"expiration_date": "2023-06-12 01:35:30+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.org/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.org/key.pem",
"expiration_date_epoch": 1686558930,
"expiration_date_epoch_utc": 1686533730,
"expiration_date_iso": "2023-06-12T01:35:30+00:00"
}
]
}
$ certbot certificates | jc --certbot -p -r
{
"certificates": [
{
"name": "example.com",
"serial_number": "3f7axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"key_type": "RSA",
"domains": [
"example.com",
"www.example.com"
],
"expiration_date": "2023-05-11 01:33:10+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.com/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.com/priv.pem"
},
{
"name": "example.org",
"serial_number": "3bcyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"key_type": "RSA",
"domains": [
"example.org",
"www.example.org"
],
"expiration_date": "2023-06-12 01:35:30+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.org/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.org/key.pem"
}
]
}
$ certbot show_account | jc --certbot -p
{
"account": {
"server": "https://acme-staging-v02.api.letsencrypt.org/directory",
"url": "https://acme-staging-v02.api.letsencrypt.org/acme/acct/123",
"email": "some@example.com"
}
}
<a id="jc.parsers.certbot.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

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

@@ -0,0 +1,199 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.clf"></a>
# jc.parsers.clf
jc - JSON Convert Common Log Format file parser
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf
Usage (module):
import jc
result = jc.parse('clf', common_log_file_output)
Schema:
Empty strings and `-` values are converted to `null`/`None`.
[
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
]
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf -p
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": 10,
"month": "Oct",
"year": 2000,
"hour": 13,
"minute": 55,
"second": 36,
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": 200,
"bytes": 2326,
"referer": null,
"user_agent": null,
"extra": null,
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0",
"epoch": 971211336,
"epoch_utc": null
},
{
"host": "1.1.1.2",
"ident": null,
"authuser": null,
"date": "11/Nov/2016:03:04:55 +0100",
"day": 11,
"month": "Nov",
"year": 2016,
"hour": 3,
"minute": 4,
"second": 55,
"tz": "+0100",
"request": "GET /",
"status": 200,
"bytes": 83,
"referer": null,
"user_agent": null,
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null,
"epoch": 1478862295,
"epoch_utc": null
},
...
]
$ cat file.log | jc --clf -p -r
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": "10",
"month": "Oct",
"year": "2000",
"hour": "13",
"minute": "55",
"second": "36",
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": "200",
"bytes": "2326",
"referer": null,
"user_agent": null,
"extra": "",
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0"
},
{
"host": "1.1.1.2",
"ident": "-",
"authuser": "-",
"date": "11/Nov/2016:03:04:55 +0100",
"day": "11",
"month": "Nov",
"year": "2016",
"hour": "03",
"minute": "04",
"second": "55",
"tz": "+0100",
"request": "GET /",
"status": "200",
"bytes": "83",
"referer": "-",
"user_agent": "-",
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null
},
...
]
<a id="jc.parsers.clf.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

117
docs/parsers/clf_s.md Normal file
View File

@@ -0,0 +1,117 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.clf_s"></a>
# jc.parsers.clf\_s
jc - JSON Convert Common Log Format file streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf-s
Usage (module):
import jc
result = jc.parse('clf_s', common_log_file_output.splitlines())
for item in result:
# do something
Schema:
Empty strings and `-` values are converted to `null`/`None`.
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf-s
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":null,"authuser":null,"date":"11/Nov/2016...}
...
$ cat file.log | jc --clf-s -r
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":"-","authuser":"-","date":"11/Nov/2016:0...}
...
<a id="jc.parsers.clf_s.parse"></a>
### parse
```python
@add_jc_meta
def parse(data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False) -> StreamingOutputType
```
Main text parsing generator function. Returns an iterable object.
Parameters:
data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Returns:
Iterable of Dictionaries
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -196,4 +196,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, aix, freebsd
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -193,4 +193,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, aix, freebsd
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -6,7 +6,7 @@
jc - JSON Convert ISO 8601 Datetime string parser
This parser supports standard ISO 8601 strings that include both date and
time. If no timezone or offset information is available in the sring, then
time. If no timezone or offset information is available in the string, then
UTC timezone is used.
Usage (cli):

View File

@@ -9,6 +9,7 @@ Options supported:
- `+noall +answer` options are supported in cases where only the answer
information is desired.
- `+axfr` option is supported on its own
- `+nsid` option is supported
The `when_epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
@@ -106,7 +107,7 @@ Schema:
]
[0] naive timestamp if "when" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -345,4 +346,4 @@ Returns:
### Parser Information
Compatibility: linux, aix, freebsd, darwin, win32, cygwin
Version 2.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 2.5 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -72,7 +72,6 @@ Examples:
...
]
$ findmnt | jc --findmnt -p -r
[
{
@@ -115,4 +114,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -40,13 +40,13 @@ Schema:
[
{
"commit": string,
"author": string,
"author_email": string,
"author": string/null,
"author_email": string/null,
"date": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"commit_by": string,
"commit_by_email": string,
"commit_by": string/null,
"commit_by_email": string/null,
"commit_by_date": string,
"message": string,
"stats" : {
@@ -61,7 +61,7 @@ Schema:
]
[0] naive timestamp if "date" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -172,4 +172,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -41,13 +41,13 @@ Schema:
{
"commit": string,
"author": string,
"author_email": string,
"author": string/null,
"author_email": string/null,
"date": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"commit_by": string,
"commit_by_email": string,
"commit_by": string/null,
"commit_by_email": string/null,
"commit_by_date": string,
"message": string,
"stats" : {
@@ -68,7 +68,7 @@ Schema:
}
[0] naive timestamp if "date" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
Examples:
@@ -108,4 +108,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -71,7 +71,7 @@ Examples:
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
quiet: bool = False) -> Union[JSONDictType, List[JSONDictType]]
```
Main text parsing function

View File

@@ -3,7 +3,7 @@
# jc.parsers.ifconfig
jc - JSON Convert `foo` command output parser
jc - JSON Convert `ifconfig` command output parser
No `ifconfig` options are supported.
@@ -42,6 +42,7 @@ Schema:
"ipv6_addr": string, # [0]
"ipv6_mask": integer, # [0]
"ipv6_scope": string, # [0]
"ipv6_scope_id": string, # [0]
"ipv6_type": string, # [0]
"rx_packets": integer,
"rx_bytes": integer,
@@ -87,10 +88,19 @@ Schema:
"ipv6: [
{
"address": string,
"scope_id": string,
"mask": integer,
"scope": string,
"type": string
}
],
"lanes": [
{
"lane": integer,
"rx_power_mw": float,
"rx_power_dbm": float,
"tx_bias_ma": float
}
]
}
]
@@ -147,6 +157,7 @@ Examples:
"ipv6": [
{
"address": "fe80::c1cb:715d:bc3e:b8a0",
"scope_id": null,
"mask": 64,
"scope": "0x20",
"type": "link"
@@ -195,6 +206,7 @@ Examples:
"ipv6": [
{
"address": "fe80::c1cb:715d:bc3e:b8a0",
"scope_id": null,
"mask": "64",
"scope": "0x20",
"type": "link"
@@ -228,4 +240,4 @@ Returns:
### Parser Information
Compatibility: linux, aix, freebsd, darwin
Version 2.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 2.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -3,13 +3,15 @@
# jc.parsers.ini
jc - JSON Convert `INI` file parser
jc - JSON Convert INI file parser
Parses standard `INI` files and files containing simple key/value pairs.
Parses standard INI files.
- Delimiter can be `=` or `:`. Missing values are supported.
- Comment prefix can be `#` or `;`. Comments must be on their own line.
- If duplicate keys are found, only the last value will be used.
- If any section names have the same name as a top-level key, the top-level
key will be overwritten by the section data.
> Note: Values starting and ending with double or single quotation marks
> will have the marks removed. If you would like to keep the quotation
@@ -27,45 +29,47 @@ Usage (module):
Schema:
ini or key/value document converted to a dictionary - see the configparser
INI document converted to a dictionary - see the python configparser
standard library documentation for more details.
{
"key1": string,
"key2": string
"<key1>": string,
"<key2>": string,
"<section1>": {
"<key1>": string,
"<key2>": string
},
"<section2>": {
"<key1>": string,
"<key2>": string
}
}
Examples:
$ cat example.ini
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
foo = fiz
bar = buz
[bitbucket.org]
User = hg
[section1]
fruit = apple
color = blue
[topsecret.server.com]
Port = 50022
ForwardX11 = no
[section2]
fruit = pear
color = green
$ cat example.ini | jc --ini -p
{
"bitbucket.org": {
"ServerAliveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "yes",
"User": "hg"
"foo": "fiz",
"bar": "buz",
"section1": {
"fruit": "apple",
"color": "blue"
},
"topsecret.server.com": {
"ServerAliveInterval": "45",
"Compression": "yes",
"CompressionLevel": "9",
"ForwardX11": "no",
"Port": "50022"
"section2": {
"fruit": "pear",
"color": "green"
}
}
@@ -87,9 +91,9 @@ Parameters:
Returns:
Dictionary representing the ini file
Dictionary representing the INI file.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 2.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

121
docs/parsers/ini_dup.md Normal file
View File

@@ -0,0 +1,121 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.ini_dup"></a>
# jc.parsers.ini\_dup
jc - JSON Convert INI with duplicate key file parser
Parses standard INI files and preserves duplicate values. All values are
contained in lists/arrays.
- Delimiter can be `=` or `:`. Missing values are supported.
- Comment prefix can be `#` or `;`. Comments must be on their own line.
- If any section names have the same name as a top-level key, the top-level
key will be overwritten by the section data.
- If multi-line values are used, each line will be a separate item in the
value list. Blank lines in multi-line values are not supported.
> Note: Values starting and ending with double or single quotation marks
> will have the marks removed. If you would like to keep the quotation
> marks, use the `-r` command-line argument or the `raw=True` argument in
> `parse()`.
Usage (cli):
$ cat foo.ini | jc --ini
Usage (module):
import jc
result = jc.parse('ini', ini_file_output)
Schema:
INI document converted to a dictionary - see the python configparser
standard library documentation for more details.
{
"<key1>": [
string
],
"<key2>": [
string
],
"<section1>": {
"<key1>": [
string
],
"<key2>": [
string
]
}
}
Examples:
$ cat example.ini
foo = fiz
bar = buz
[section1]
fruit = apple
color = blue
color = red
[section2]
fruit = pear
fruit = peach
color = green
$ cat example.ini | jc --ini -p
{
"foo": [
"fiz"
],
"bar": [
"buz"
],
"section1": {
"fruit": [
"apple"
],
"color": [
"blue",
"red"
]
},
"section2": {
"fruit": [
"pear",
"peach"
],
"color": [
"green"
]
}
}
<a id="jc.parsers.ini_dup.parse"></a>
### parse
```python
def parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary representing the INI file.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -130,4 +130,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

111
docs/parsers/iwconfig.md Normal file
View File

@@ -0,0 +1,111 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.iwconfig"></a>
# jc.parsers.iwconfig
jc - JSON Convert `iwconfig` command output parser
No `iwconfig` options are supported.
Usage (cli):
$ iwconfig | jc --iwconfig
or
$ jc iwconfig
Usage (module):
import jc
result = jc.parse('iwconfig', iwconfig_command_output)
Schema:
[
{
"name": string,
"protocol": string,
"essid": string,
"mode": string,
"frequency": float,
"frequency_unit": string,
"access_point": string,
"bit_rate": float,
"bit_rate_unit": string,
"tx_power": integer,
"tx_power_unit": string,
"retry_short_limit": integer,
"rts_threshold": boolean,
"fragment_threshold": boolean,
"power_management": boolean,
"link_quality": string,
"signal_level": integer,
"signal_level_unit": string,
"rx_invalid_nwid": integer,
"rx_invalid_crypt": integer,
"rx_invalid_frag": integer,
"tx_excessive_retries": integer,
"invalid_misc": integer,
"missed_beacon": integer
}
]
Examples:
$ iwconfig | jc --iwconfig -p
[
{
"name": "wlp5s0",
"protocol": "IEEE 802.11",
"essid": "BLABLABLA",
"mode": "Managed",
"frequency": 5.18,
"frequency_unit": "GHz",
"access_point": "E6:64:DA:16:51:BF",
"bit_rate": 6.0,
"bit_rate_unit": "Mb/s",
"tx_power": 30,
"tx_power_unit": "dBm",
"retry_short_limit": 7,
"rts_threshold": false,
"fragment_threshold": false,
"power_management": true,
"link_quality": "61/70",
"signal_level": -49,
"signal_level_unit": "dBm",
"rx_invalid_nwid": 0,
"rx_invalid_crypt": 0,
"rx_invalid_frag": 0,
"tx_excessive_retries": 0,
"invalid_misc": 2095,
"missed_beacon": 0
}
]
<a id="jc.parsers.iwconfig.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.1 by Thomas Vincent (vrince@gmail.com)

View File

@@ -3,7 +3,7 @@
# jc.parsers.kv
jc - JSON Convert `Key/Value` file parser
jc - JSON Convert `Key/Value` file and string parser
Supports files containing simple key/value pairs.
@@ -26,8 +26,8 @@ Usage (module):
Schema:
key/value document converted to a dictionary - see the configparser standard
library documentation for more details.
Key/Value document converted to a dictionary - see the python configparser
standard library documentation for more details.
{
"key1": string,
@@ -41,6 +41,7 @@ Examples:
name = John Doe
address=555 California Drive
age: 34
; comments can include # or ;
# delimiter can be = or :
# quoted values have quotation marks stripped by default
@@ -65,8 +66,6 @@ def parse(data, raw=False, quiet=False)
Main text parsing function
Note: this is just a wrapper for jc.parsers.ini
Parameters:
data: (string) text data to parse
@@ -75,9 +74,9 @@ Parameters:
Returns:
Dictionary representing the key/value file
Dictionary representing a Key/Value pair document.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 2.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -5,7 +5,7 @@
jc - JSON Convert `last` and `lastb` command output parser
Supports `-w` and `-F` options.
Supports `-w`, `-F`, and `-x` options.
Calculated epoch time fields are naive (i.e. based on the local time of the
system the parser is run on) since there is no timezone information in the
@@ -127,4 +127,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, aix, freebsd
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -99,4 +99,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, aix, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

89
docs/parsers/lsattr.md Normal file
View File

@@ -0,0 +1,89 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.lsattr"></a>
# jc.parsers.lsattr
jc - JSON Convert `lsattr` command output parser
Usage (cli):
$ lsattr | jc --lsattr
or
$ jc lsattr
Usage (module):
import jc
result = jc.parse('lsattr', lsattr_command_output)
Schema:
Information from https://github.com/mirror/busybox/blob/2d4a3d9e6c1493a9520b907e07a41aca90cdfd94/e2fsprogs/e2fs_lib.c#L40
used to define field names
[
{
"file": string,
"compressed_file": Optional[boolean],
"compressed_dirty_file": Optional[boolean],
"compression_raw_access": Optional[boolean],
"secure_deletion": Optional[boolean],
"undelete": Optional[boolean],
"synchronous_updates": Optional[boolean],
"synchronous_directory_updates": Optional[boolean],
"immutable": Optional[boolean],
"append_only": Optional[boolean],
"no_dump": Optional[boolean],
"no_atime": Optional[boolean],
"compression_requested": Optional[boolean],
"encrypted": Optional[boolean],
"journaled_data": Optional[boolean],
"indexed_directory": Optional[boolean],
"no_tailmerging": Optional[boolean],
"top_of_directory_hierarchies": Optional[boolean],
"extents": Optional[boolean],
"no_cow": Optional[boolean],
"casefold": Optional[boolean],
"inline_data": Optional[boolean],
"project_hierarchy": Optional[boolean],
"verity": Optional[boolean],
}
]
Examples:
$ sudo lsattr /etc/passwd | jc --lsattr
[
{
"file": "/etc/passwd",
"extents": true
}
]
<a id="jc.parsers.lsattr.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Mark Rotner (rotner.mr@gmail.com)

View File

@@ -102,6 +102,46 @@ Schema:
]
}
},
"cdc_mbim": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"cdc_mbim_extended": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"videocontrol_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
}
],
"videostreaming_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
}
],
"endpoint_descriptors": [
{
"<item>": {
@@ -290,4 +330,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -25,7 +25,7 @@ Schema:
"filesystem": string,
"mount_point": string,
"type": string,
"access": [
"options": [
string
]
}
@@ -39,7 +39,7 @@ Example:
"filesystem": "sysfs",
"mount_point": "/sys",
"type": "sysfs",
"access": [
"options": [
"rw",
"nosuid",
"nodev",
@@ -51,7 +51,7 @@ Example:
"filesystem": "proc",
"mount_point": "/proc",
"type": "proc",
"access": [
"options": [
"rw",
"nosuid",
"nodev",
@@ -63,7 +63,7 @@ Example:
"filesystem": "udev",
"mount_point": "/dev",
"type": "devtmpfs",
"access": [
"options": [
"rw",
"nosuid",
"relatime",
@@ -96,6 +96,6 @@ Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, freebsd
Compatibility: linux, darwin, freebsd, aix
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -376,6 +376,6 @@ Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, freebsd
Compatibility: linux, darwin, freebsd, win32
Version 1.13 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.14 by Kelly Brazil (kellyjonbrazil@gmail.com)

178
docs/parsers/openvpn.md Normal file
View File

@@ -0,0 +1,178 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.openvpn"></a>
# jc.parsers.openvpn
jc - JSON Convert openvpn-status.log file parser
The `*_epoch` calculated timestamp fields are naive. (i.e. based on
the local time of the system the parser is run on)
Usage (cli):
$ cat openvpn-status.log | jc --openvpn
Usage (module):
import jc
result = jc.parse('openvpn', openvpn_status_log_file_output)
Schema:
{
"clients": [
{
"common_name": string,
"real_address": string,
"real_address_prefix": integer, # [0]
"real_address_port": integer, # [0]
"bytes_received": integer,
"bytes_sent": integer,
"connected_since": string,
"connected_since_epoch": integer,
"updated": string,
"updated_epoch": integer,
}
],
"routing_table": [
{
"virtual_address": string,
"virtual_address_prefix": integer, # [0]
"virtual_address_port": integer, # [0]
"common_name": string,
"real_address": string,
"real_address_prefix": integer, # [0]
"real_address_port": integer, # [0]
"last_reference": string,
"last_reference_epoch": integer,
}
],
"global_stats": {
"max_bcast_mcast_queue_len": integer
}
}
[0] null/None if not found
Examples:
$ cat openvpn-status.log | jc --openvpn -p
{
"clients": [
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10",
"bytes_received": 334948,
"bytes_sent": 1973012,
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015",
"real_address_prefix": null,
"real_address_port": 49502,
"connected_since_epoch": 1434626583,
"updated_epoch": 1434640335
},
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10",
"bytes_received": 334948,
"bytes_sent": 1973012,
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015",
"real_address_prefix": null,
"real_address_port": 49503,
"connected_since_epoch": 1434626583,
"updated_epoch": 1434640335
}
],
"routing_table": [
{
"virtual_address": "192.168.255.118",
"common_name": "baz@example.com",
"real_address": "10.10.10.10",
"last_reference": "Thu Jun 18 08:12:09 2015",
"virtual_address_prefix": null,
"virtual_address_port": null,
"real_address_prefix": null,
"real_address_port": 63414,
"last_reference_epoch": 1434640329
},
{
"virtual_address": "10.200.0.0",
"common_name": "baz@example.com",
"real_address": "10.10.10.10",
"last_reference": "Thu Jun 18 08:12:09 2015",
"virtual_address_prefix": 16,
"virtual_address_port": null,
"real_address_prefix": null,
"real_address_port": 63414,
"last_reference_epoch": 1434640329
}
],
"global_stats": {
"max_bcast_mcast_queue_len": 0
}
}
$ cat openvpn-status.log | jc --openvpn -p -r
{
"clients": [
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10:49502",
"bytes_received": "334948",
"bytes_sent": "1973012",
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015"
},
{
"common_name": "foo@example.com",
"real_address": "10.10.10.10:49503",
"bytes_received": "334948",
"bytes_sent": "1973012",
"connected_since": "Thu Jun 18 04:23:03 2015",
"updated": "Thu Jun 18 08:12:15 2015"
}
],
"routing_table": [
{
"virtual_address": "192.168.255.118",
"common_name": "baz@example.com",
"real_address": "10.10.10.10:63414",
"last_reference": "Thu Jun 18 08:12:09 2015"
},
{
"virtual_address": "10.200.0.0/16",
"common_name": "baz@example.com",
"real_address": "10.10.10.10:63414",
"last_reference": "Thu Jun 18 08:12:09 2015"
}
],
"global_stats": {
"max_bcast_mcast_queue_len": "0"
}
}
<a id="jc.parsers.openvpn.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -21,12 +21,15 @@ Usage (module):
Schema:
{
'partition': string,
'name': string,
'short_name': string,
'type': string
"partition": string,
"efi_bootmgr": string, # [0]
"name": string,
"short_name": string,
"type": string
}
[0] only exists if an EFI boot manager is detected
Examples:
$ os-prober | jc --os-prober -p
@@ -60,4 +63,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

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

@@ -0,0 +1,75 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.pgpass"></a>
# jc.parsers.pgpass
jc - JSON Convert PostgreSQL password file parser
Usage (cli):
$ cat /var/lib/postgresql/.pgpass | jc --pgpass
Usage (module):
import jc
result = jc.parse('pgpass', postgres_password_file)
Schema:
[
{
"hostname": string,
"port": string,
"database": string,
"username": string,
"password": string
}
]
Examples:
$ cat /var/lib/postgresql/.pgpass | jc --pgpass -p
[
{
"hostname": "dbserver",
"port": "*",
"database": "db1",
"username": "dbuser",
"password": "pwd123"
},
{
"hostname": "dbserver2",
"port": "8888",
"database": "inventory",
"username": "joe:user",
"password": "abc123"
},
...
]
<a id="jc.parsers.pgpass.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -185,4 +185,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -106,4 +106,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -5,7 +5,7 @@
jc - JSON Convert PLIST file parser
Converts binary and XML PLIST files.
Converts binary, XML, and NeXTSTEP PLIST files.
Binary values are converted into an ASCII hex representation.
@@ -69,9 +69,9 @@ Parameters:
Returns:
List of Dictionaries. Raw or processed structured data.
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -6,7 +6,7 @@
jc - JSON Convert Proc file output parser
This parser automatically identifies the Proc file and calls the
corresponding parser to peform the parsing.
corresponding parser to perform the parsing.
Magic syntax for converting `/proc` files is also supported by running
`jc /proc/<path to file>`. Any `jc` options must be specified before the
@@ -139,4 +139,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -114,7 +114,8 @@ Examples:
"mw",
"me",
"dw",
"sd"
"sd",
"mp"
],
"VmFlags_pretty": [
"readable",

View File

@@ -22,6 +22,13 @@ Schema:
[
{
"interfaces": [
{
"id": string,
"mac": string,
"name": string,
}
]
"destination": string,
"gateway": string,
"genmask": string,
@@ -129,6 +136,6 @@ Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Compatibility: linux, win32
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -114,4 +114,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -7,6 +7,8 @@ jc - JSON Convert Semantic Version string parser
This parser conforms to the specification at https://semver.org/
See Also: `ver` parser.
Usage (cli):
$ echo 1.2.3-rc.1+44837 | jc --semver

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

@@ -0,0 +1,136 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.srt"></a>
# jc.parsers.srt
jc - JSON Convert `SRT` file parser
Usage (cli):
$ cat foo.srt | jc --srt
Usage (module):
import jc
result = jc.parse('srt', srt_file_output)
Schema:
[
{
"index": int,
"start": {
"hours": int,
"minutes": int,
"seconds": int,
"milliseconds": int,
"timestamp": string
},
"end": {
"hours": int,
"minutes": int,
"seconds": int,
"milliseconds": int,
"timestamp": string
},
"content": string
}
]
Examples:
$ cat attack_of_the_clones.srt
1
00:02:16,612 --> 00:02:19,376
Senator, we're making
our final approach into Coruscant.
2
00:02:19,482 --> 00:02:21,609
Very good, Lieutenant.
...
$ cat attack_of_the_clones.srt | jc --srt
[
{
"index": 1,
"start": {
"hours": 0,
"minutes": 2,
"seconds": 16,
"milliseconds": 612,
"timestamp": "00:02:16,612"
},
"end": {
"hours": 0,
"minutes": 2,
"seconds": 19,
"milliseconds": 376,
"timestamp": "00:02:19,376"
},
"content": "Senator, we're making\nour final approach into Coruscant."
},
{
"index": 2,
"start": {
"hours": 0,
"minutes": 2,
"seconds": 19,
"milliseconds": 482,
"timestamp": "00:02:19,482"
},
"end": {
"hours": 0,
"minutes": 2,
"seconds": 21,
"milliseconds": 609,
"timestamp": "00:02:21,609"
},
"content": "Very good, Lieutenant."
},
...
]
<a id="jc.parsers.srt.parse_timestamp"></a>
### parse\_timestamp
```python
def parse_timestamp(timestamp: str) -> Dict
```
timestamp: "hours:minutes:seconds,milliseconds" --->
{
"hours": "hours",
"minutes": "minutes",
"seconds": "seconds",
"milliseconds": "milliseconds",
"timestamp": "hours:minutes:seconds,milliseconds"
}
<a id="jc.parsers.srt.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Mark Rotner (rotner.mr@gmail.com)

View File

@@ -5,9 +5,6 @@
jc - JSON Convert `ss` command output parser
Extended information options like `-e` and `-p` are not supported and may
cause parsing irregularities.
Usage (cli):
$ ss | jc --ss
@@ -28,21 +25,29 @@ field names
[
{
"netid": string,
"state": string,
"recv_q": integer,
"send_q": integer,
"local_address": string,
"local_port": string,
"local_port_num": integer,
"peer_address": string,
"peer_port": string,
"peer_port_num": integer,
"interface": string,
"link_layer" string,
"channel": string,
"path": string,
"pid": integer
"netid": string,
"state": string,
"recv_q": integer,
"send_q": integer,
"local_address": string,
"local_port": string,
"local_port_num": integer,
"peer_address": string,
"peer_port": string,
"peer_port_num": integer,
"interface": string,
"link_layer" string,
"channel": string,
"path": string,
"pid": integer,
"opts": {
"process_id": {
"<process_id>": {
"user": string,
"file_descriptor": string
}
}
}
}
]
@@ -303,4 +308,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)

548
docs/parsers/ssh_conf.md Normal file
View File

@@ -0,0 +1,548 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.ssh_conf"></a>
# jc.parsers.ssh\_conf
jc - JSON Convert `ssh` configuration file and `ssh -G` command output parser
This parser will work with `ssh` configuration files or the output of
`ssh -G`. Any `Match` blocks in the `ssh` configuration file will be
ignored.
Usage (cli):
$ ssh -G hostname | jc --ssh-conf
or
$ jc ssh -G hostname
or
$ cat ~/.ssh/config | jc --ssh-conf
Usage (module):
import jc
result = jc.parse('ssh_conf', ssh_conf_output)
Schema:
[
{
"host": string,
"host_list": [
string
],
"addkeystoagent": string,
"addressfamily": string,
"batchmode": string,
"bindaddress": string,
"bindinterface": string,
"canonicaldomains": [
string
],
"canonicalizefallbacklocal": string,
"canonicalizehostname": string,
"canonicalizemaxdots": integer,
"canonicalizepermittedcnames": [
string
],
"casignaturealgorithms": [
string
],
"certificatefile": [
string
],
"checkhostip": string,
"ciphers": [
string
],
"clearallforwardings": string,
"compression": string,
"connectionattempts": integer,
"connecttimeout": integer,
"controlmaster": string,
"controlpath": string,
"controlpersist": string,
"dynamicforward": string,
"enableescapecommandline": string,
"enablesshkeysign": string,
"escapechar": string,
"exitonforwardfailure": string,
"fingerprinthash": string,
"forkafterauthentication": string,
"forwardagent": string,
"forwardx11": string,
"forwardx11timeout": integer,
"forwardx11trusted": string,
"gatewayports": string,
"globalknownhostsfile": [
string
],
"gssapiauthentication": string,
"gssapidelegatecredentials": string,
"hashknownhosts": string,
"hostbasedacceptedalgorithms": [
string
],
"hostbasedauthentication": string,
"hostkeyalgorithms": [
string
],
"hostkeyalias": string,
"hostname": string,
"identitiesonly": string,
"identityagent": string,
"identityfile": [
string
],
"ignoreunknown": string,
"include": [
string
],
"ipqos": [
string
],
"kbdinteractiveauthentication": string,
"kbdinteractivedevices": [
string
],
"kexalgorithms": [
string
],
"kexalgorithms_strategy": string,
"knownhostscommand": string,
"localcommand": string,
"localforward": [
string
],
"loglevel": string,
"logverbose": [
string
],
"macs": [
string
],
"macs_strategy": string,
"nohostauthenticationforlocalhost": string,
"numberofpasswordprompts": integer,
"passwordauthentication": string,
"permitlocalcommand": string,
"permitremoteopen": [
string
],
"pkcs11provider": string,
"port": integer,
"preferredauthentications": [
string
],
"protocol": integer,
"proxycommand": string,
"proxyjump": [
string
],
"proxyusefdpass": string,
"pubkeyacceptedalgorithms": [
string
],
"pubkeyacceptedalgorithms_strategy": string,
"pubkeyauthentication": string,
"rekeylimit": string,
"remotecommand": string,
"remoteforward": string,
"requesttty": string,
"requiredrsasize": integer,
"revokedhostkeys": string,
"securitykeyprovider": string,
"sendenv": [
string
],
"serveralivecountmax": integer,
"serveraliveinterval": integer,
"sessiontype": string,
"setenv": [
string
],
"stdinnull": string,
"streamlocalbindmask": string,
"streamlocalbindunlink": string,
"stricthostkeychecking": string,
"syslogfacility": string,
"tcpkeepalive": string,
"tunnel": string,
"tunneldevice": string,
"updatehostkeys": string,
"user": string,
"userknownhostsfile": [
string
],
"verifyhostkeydns": string,
"visualhostkey": string,
"xauthlocation": string
}
]
Examples:
$ ssh -G - | jc --ssh-conf -p
[
{
"user": "foo",
"hostname": "-",
"port": 22,
"addressfamily": "any",
"batchmode": "no",
"canonicalizefallbacklocal": "yes",
"canonicalizehostname": "false",
"checkhostip": "no",
"compression": "no",
"controlmaster": "false",
"enablesshkeysign": "no",
"clearallforwardings": "no",
"exitonforwardfailure": "no",
"fingerprinthash": "SHA256",
"forwardx11": "no",
"forwardx11trusted": "no",
"gatewayports": "no",
"gssapiauthentication": "no",
"gssapidelegatecredentials": "no",
"hashknownhosts": "no",
"hostbasedauthentication": "no",
"identitiesonly": "no",
"kbdinteractiveauthentication": "yes",
"nohostauthenticationforlocalhost": "no",
"passwordauthentication": "yes",
"permitlocalcommand": "no",
"proxyusefdpass": "no",
"pubkeyauthentication": "true",
"requesttty": "auto",
"sessiontype": "default",
"stdinnull": "no",
"forkafterauthentication": "no",
"streamlocalbindunlink": "no",
"stricthostkeychecking": "ask",
"tcpkeepalive": "yes",
"tunnel": "false",
"verifyhostkeydns": "false",
"visualhostkey": "no",
"updatehostkeys": "true",
"applemultipath": "no",
"canonicalizemaxdots": 1,
"connectionattempts": 1,
"forwardx11timeout": 1200,
"numberofpasswordprompts": 3,
"serveralivecountmax": 3,
"serveraliveinterval": 0,
"ciphers": [
"chacha20-poly1305@openssh.com",
"aes128-ctr",
"aes192-ctr",
"aes256-ctr",
"aes128-gcm@openssh.com",
"aes256-gcm@openssh.com"
],
"hostkeyalgorithms": [
"ssh-ed25519-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
"rsa-sha2-512-cert-v01@openssh.com",
"rsa-sha2-256-cert-v01@openssh.com",
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"rsa-sha2-512",
"rsa-sha2-256"
],
"hostbasedacceptedalgorithms": [
"ssh-ed25519-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
"rsa-sha2-512-cert-v01@openssh.com",
"rsa-sha2-256-cert-v01@openssh.com",
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"rsa-sha2-512",
"rsa-sha2-256"
],
"kexalgorithms": [
"sntrup761x25519-sha512@openssh.com",
"curve25519-sha256",
"curve25519-sha256@libssh.org",
"ecdh-sha2-nistp256",
"ecdh-sha2-nistp384",
"ecdh-sha2-nistp521",
"diffie-hellman-group-exchange-sha256",
"diffie-hellman-group16-sha512",
"diffie-hellman-group18-sha512",
"diffie-hellman-group14-sha256"
],
"casignaturealgorithms": [
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"rsa-sha2-512",
"rsa-sha2-256"
],
"loglevel": "INFO",
"macs": [
"umac-64-etm@openssh.com",
"umac-128-etm@openssh.com",
"hmac-sha2-256-etm@openssh.com",
"hmac-sha2-512-etm@openssh.com",
"hmac-sha1-etm@openssh.com",
"umac-64@openssh.com",
"umac-128@openssh.com",
"hmac-sha2-256",
"hmac-sha2-512",
"hmac-sha1"
],
"securitykeyprovider": "$SSH_SK_PROVIDER",
"pubkeyacceptedalgorithms": [
"ssh-ed25519-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
"rsa-sha2-512-cert-v01@openssh.com",
"rsa-sha2-256-cert-v01@openssh.com",
"ssh-ed25519",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"rsa-sha2-512",
"rsa-sha2-256"
],
"xauthlocation": "/usr/X11R6/bin/xauth",
"identityfile": [
"~/.ssh/id_rsa",
"~/.ssh/id_ecdsa",
"~/.ssh/id_ecdsa_sk",
"~/.ssh/id_ed25519",
"~/.ssh/id_ed25519_sk",
"~/.ssh/id_xmss",
"~/.ssh/id_dsa"
],
"canonicaldomains": [
"none"
],
"globalknownhostsfile": [
"/etc/ssh/ssh_known_hosts",
"/etc/ssh/ssh_known_hosts2"
],
"userknownhostsfile": [
"/Users/foo/.ssh/known_hosts",
"/Users/foo/.ssh/known_hosts2"
],
"sendenv": [
"LANG",
"LC_*"
],
"logverbose": [
"none"
],
"permitremoteopen": [
"any"
],
"addkeystoagent": "false",
"forwardagent": "no",
"connecttimeout": null,
"tunneldevice": "any:any",
"canonicalizepermittedcnames": [
"none"
],
"controlpersist": "no",
"escapechar": "~",
"ipqos": [
"af21",
"cs1"
],
"rekeylimit": "0 0",
"streamlocalbindmask": "0177",
"syslogfacility": "USER"
}
]
$ cat ~/.ssh/config | jc --ssh-conf -p
[
{
"host": "server1",
"host_list": [
"server1"
],
"hostname": "server1.cyberciti.biz",
"user": "nixcraft",
"port": 4242,
"identityfile": [
"/nfs/shared/users/nixcraft/keys/server1/id_rsa"
]
},
{
"host": "nas01",
"host_list": [
"nas01"
],
"hostname": "192.168.1.100",
"user": "root",
"identityfile": [
"~/.ssh/nas01.key"
]
},
{
"host": "aws.apache",
"host_list": [
"aws.apache"
],
"hostname": "1.2.3.4",
"user": "wwwdata",
"identityfile": [
"~/.ssh/aws.apache.key"
]
},
{
"host": "uk.gw.lan uk.lan",
"host_list": [
"uk.gw.lan",
"uk.lan"
],
"hostname": "192.168.0.251",
"user": "nixcraft",
"proxycommand": "ssh nixcraft@gateway.uk.cyberciti.biz nc %h %p 2> /dev/null"
},
{
"host": "proxyus",
"host_list": [
"proxyus"
],
"hostname": "vps1.cyberciti.biz",
"user": "breakfree",
"identityfile": [
"~/.ssh/vps1.cyberciti.biz.key"
],
"localforward": [
"3128 127.0.0.1:3128"
]
},
{
"host": "*",
"host_list": [
"*"
],
"forwardagent": "no",
"forwardx11": "no",
"forwardx11trusted": "yes",
"user": "nixcraft",
"port": 22,
"protocol": 2,
"serveraliveinterval": 60,
"serveralivecountmax": 30
}
]
$ cat ~/.ssh/config | jc --ssh-conf -p -r
[
{
"host": "server1",
"host_list": [
"server1"
],
"hostname": "server1.cyberciti.biz",
"user": "nixcraft",
"port": "4242",
"identityfile": [
"/nfs/shared/users/nixcraft/keys/server1/id_rsa"
]
},
{
"host": "nas01",
"host_list": [
"nas01"
],
"hostname": "192.168.1.100",
"user": "root",
"identityfile": [
"~/.ssh/nas01.key"
]
},
{
"host": "aws.apache",
"host_list": [
"aws.apache"
],
"hostname": "1.2.3.4",
"user": "wwwdata",
"identityfile": [
"~/.ssh/aws.apache.key"
]
},
{
"host": "uk.gw.lan uk.lan",
"host_list": [
"uk.gw.lan",
"uk.lan"
],
"hostname": "192.168.0.251",
"user": "nixcraft",
"proxycommand": "ssh nixcraft@gateway.uk.cyberciti.biz nc %h %p 2> /dev/null"
},
{
"host": "proxyus",
"host_list": [
"proxyus"
],
"hostname": "vps1.cyberciti.biz",
"user": "breakfree",
"identityfile": [
"~/.ssh/vps1.cyberciti.biz.key"
],
"localforward": [
"3128 127.0.0.1:3128"
]
},
{
"host": "*",
"host_list": [
"*"
],
"forwardagent": "no",
"forwardx11": "no",
"forwardx11trusted": "yes",
"user": "nixcraft",
"port": "22",
"protocol": "2",
"serveraliveinterval": "60",
"serveralivecountmax": "30"
}
]
<a id="jc.parsers.ssh_conf.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -3,7 +3,7 @@
# jc.parsers.sshd\_conf
jc - JSON Convert sshd configuration file and `sshd -T` command output parser
jc - JSON Convert `sshd` configuration file and `sshd -T` command output parser
This parser will work with `sshd` configuration files or the output of
`sshd -T`. Any `Match` blocks in the `sshd` configuration file will be
@@ -161,7 +161,7 @@ Schema:
Examples:
$ sshd -T | jc --sshd_conf -p
$ sshd -T | jc --sshd-conf -p
{
"acceptenv": [
"LANG",
@@ -376,7 +376,7 @@ Examples:
"subsystem_command": "/usr/lib/openssh/sftp-server"
}
$ sshd -T | jc --sshd_conf -p -r
$ sshd -T | jc --sshd-conf -p -r
{
"acceptenv": [
"LANG",
@@ -504,4 +504,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -193,4 +193,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.12 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.13 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -107,4 +107,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -53,7 +53,7 @@ Blank values converted to `null`/`None`.
]
[0] naive timestamp if "timestamp" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
[2] this field exists if the syslog line is not parsable. The value
is the original syslog line.

View File

@@ -64,7 +64,7 @@ Blank values converted to `null`/`None`.
}
[0] naive timestamp if "timestamp" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[1] timezone aware timestamp available for UTC, else null
[2] this field exists if the syslog line is not parsable. The value
is the original syslog line.

View File

@@ -5,6 +5,8 @@
jc - JSON Convert `timedatectl` command output parser
Also supports the `timesync-status` option.
The `epoch_utc` calculated timestamp field is timezone-aware and is only
available if the `universal_time` field is available.
@@ -34,7 +36,24 @@ Schema:
"system_clock_synchronized": boolean,
"systemd-timesyncd.service_active": boolean,
"rtc_in_local_tz": boolean,
"dst_active": boolean
"dst_active": boolean,
"server": string,
"poll_interval": string,
"leap": string,
"version": integer,
"stratum": integer,
"reference": string,
"precision": string,
"root_distance": string,
"offset": float,
"offset_unit": string,
"delay": float,
"delay_unit": string,
"jitter": float,
"jitter_unit": string,
"packet_count": integer,
"frequency": float,
"frequency_unit": string
}
Examples:
@@ -87,4 +106,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)

81
docs/parsers/toml.md Normal file
View File

@@ -0,0 +1,81 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.toml"></a>
# jc.parsers.toml
jc - JSON Convert TOML file parser
Usage (cli):
$ cat file.toml | jc --toml
Usage (module):
import jc
result = jc.parse('toml', toml_file_output)
Schema:
TOML Document converted to a Dictionary.
See https://toml.io/en/ for details.
{
"key1": string/int/float/boolean/null/array/object,
"key2": string/int/float/boolean/null/array/object
}
Examples:
$ cat file.toml
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00
[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
$ cat file.toml | jc --toml -p
{
"title": "TOML Example",
"owner": {
"name": "Tom Preston-Werner",
"dob": 296667120,
"dob_iso": "1979-05-27T07:32:00-08:00"
},
"database": {
"enabled": true,
"ports": [
8000,
8001,
8002
]
}
}
<a id="jc.parsers.toml.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -161,4 +161,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -42,8 +42,7 @@ Parameters:
underscore '_'. You should also ensure headers are
lowercase by using .lower().
Also, ensure there are no blank lines (list items)
in the data.
Also, ensure there are no blank rows in the data.
Returns:

112
docs/parsers/ver.md Normal file
View File

@@ -0,0 +1,112 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.ver"></a>
# jc.parsers.ver
jc - JSON Convert Version string output parser
Best-effort attempt to parse various styles of version numbers. This parser
is based off of the version parser included in the CPython distutils
libary.
If the version string conforms to some de facto-standard versioning rules
followed by many developers a `strict` key will be present in the output
with a value of `true` along with the named parsed components.
All other version strings will have a `strict` value of `false` and a
`components` key will contain a list of detected parts of the version
string.
See Also: `semver` parser.
Usage (cli):
$ echo 1.2a1 | jc --ver
Usage (module):
import jc
result = jc.parse('ver', version_string_output)
Schema:
{
"major": integer,
"minor": integer,
"patch": integer,
"prerelease": string,
"prerelease_num": integer,
"components": [
integer/string
],
"strict": boolean
}
Examples:
$ echo 1.2a1 | jc --ver -p
{
"major": 1,
"minor": 2,
"patch": 0,
"prerelease": "a",
"prerelease_num": 1,
"strict": true
}
$ echo 1.2a1 | jc --ver -p -r
{
"major": "1",
"minor": "2",
"patch": "0",
"prerelease": "a",
"prerelease_num": "1",
"strict": true
}
$ echo 1.2beta3 | jc --ver -p
{
"components": [
1,
2,
"beta",
3
],
"strict": false
}
$ echo 1.2beta3 | jc --ver -p -r
{
"components": [
"1",
"2",
"beta",
"3"
],
"strict": false
}
<a id="jc.parsers.ver.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

108
docs/parsers/veracrypt.md Normal file
View File

@@ -0,0 +1,108 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.veracrypt"></a>
# jc.parsers.veracrypt
jc - JSON Convert `veracrypt` command output parser
Supports the following `veracrypt` subcommands:
- `veracrypt --text --list`
- `veracrypt --text --list --verbose`
- `veracrypt --text --volume-properties <volume>`
Usage (cli):
$ veracrypt --text --list | jc --veracrypt
or
$ jc veracrypt --text --list
Usage (module):
import jc
result = jc.parse('veracrypt', veracrypt_command_output)
Schema:
Volume:
[
{
"slot": integer,
"path": string,
"device": string,
"mountpoint": string,
"size": string,
"type": string,
"readonly": string,
"hidden_protected": string,
"encryption_algo": string,
"pk_size": string,
"sk_size": string,
"block_size": string,
"mode": string,
"prf": string,
"format_version": integer,
"backup_header": string
}
]
Examples:
$ veracrypt --text --list | jc --veracrypt -p
[
{
"slot": 1,
"path": "/dev/sdb1",
"device": "/dev/mapper/veracrypt1",
"mountpoint": "/home/bob/mount/encrypt/sdb1"
}
]
$ veracrypt --text --list --verbose | jc --veracrypt -p
[
{
"slot": 1,
"path": "/dev/sdb1",
"device": "/dev/mapper/veracrypt1",
"mountpoint": "/home/bob/mount/encrypt/sdb1",
"size": "522 MiB",
"type": "Normal",
"readonly": "No",
"hidden_protected": "No",
"encryption_algo": "AES",
"pk_size": "256 bits",
"sk_size": "256 bits",
"block_size": "128 bits",
"mode": "XTS",
"prf": "HMAC-SHA-512",
"format_version": 2,
"backup_header": "Yes"
}
]
<a id="jc.parsers.veracrypt.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Jake Ob (iakopap at gmail.com)

View File

@@ -123,4 +123,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -32,6 +32,7 @@ Schema:
"tbs_certificate": {
"version": string,
"serial_number": string, # [0]
"serial_number_str": string,
"signature": {
"algorithm": string,
"parameters": string/null,
@@ -43,7 +44,9 @@ Schema:
"organization_name": array/string,
"organizational_unit_name": array/string,
"common_name": string,
"email_address": string
"email_address": string,
"serial_number": string, # [0]
"serial_number_str": string
},
"validity": {
"not_before": integer, # [1]
@@ -58,7 +61,9 @@ Schema:
"organization_name": array/string,
"organizational_unit_name": array/string,
"common_name": string,
"email_address": string
"email_address": string,
"serial_number": string, # [0]
"serial_number_str": string
},
"subject_public_key_info": {
"algorithm": {
@@ -428,4 +433,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

282
docs/parsers/x509_csr.md Normal file
View File

@@ -0,0 +1,282 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.x509_csr"></a>
# jc.parsers.x509\_csr
jc - JSON Convert X.509 Certificate Request format file parser
This parser will convert DER and PEM encoded X.509 certificate request files.
Usage (cli):
$ cat certificateRequest.pem | jc --x509-csr
Usage (module):
import jc
result = jc.parse('x509_csr', x509_csr_file_output)
Schema:
[
{
"certification_request_info": {
"version": string,
"serial_number": string, # [0]
"serial_number_str": string,
"signature": {
"algorithm": string,
"parameters": string/null,
},
"issuer": {
"country_name": string,
"state_or_province_name" string,
"locality_name": string,
"organization_name": array/string,
"organizational_unit_name": array/string,
"common_name": string,
"email_address": string,
"serial_number": string, # [0]
"serial_number_str": string
},
"validity": {
"not_before": integer, # [1]
"not_after": integer, # [1]
"not_before_iso": string,
"not_after_iso": string
},
"subject": {
"country_name": string,
"state_or_province_name": string,
"locality_name": string,
"organization_name": array/string,
"organizational_unit_name": array/string,
"common_name": string,
"email_address": string,
"serial_number": string, # [0]
"serial_number_str": string
},
"subject_public_key_info": {
"algorithm": {
"algorithm": string,
"parameters": string/null,
},
"public_key": {
"modulus": string, # [0]
"public_exponent": integer
}
},
"issuer_unique_id": string/null,
"subject_unique_id": string/null,
"extensions": [
{
"extn_id": string,
"critical": boolean,
"extn_value": array/object/string/integer # [2]
}
]
},
"signature_algorithm": {
"algorithm": string,
"parameters": string/null
},
"signature_value": string # [0]
}
]
[0] in colon-delimited hex notation
[1] time-zone-aware (UTC) epoch timestamp
[2] See below for well-known Extension schemas:
Basic Constraints:
{
"extn_id": "basic_constraints",
"critical": boolean,
"extn_value": {
"ca": boolean,
"path_len_constraint": string/null
}
}
Key Usage:
{
"extn_id": "key_usage",
"critical": boolean,
"extn_value": [
string
]
}
Key Identifier:
{
"extn_id": "key_identifier",
"critical": boolean,
"extn_value": string # [0]
}
Authority Key Identifier:
{
"extn_id": "authority_key_identifier",
"critical": boolean,
"extn_value": {
"key_identifier": string, # [0]
"authority_cert_issuer": string/null,
"authority_cert_serial_number": string/null
}
}
Subject Alternative Name:
{
"extn_id": "subject_alt_name",
"critical": boolean,
"extn_value": [
string
]
}
Certificate Policies:
{
"extn_id": "certificate_policies",
"critical": boolean,
"extn_value": [
{
"policy_identifier": string,
"policy_qualifiers": [ array or null
{
"policy_qualifier_id": string,
"qualifier": string
}
]
}
]
}
Signed Certificate Timestamp List:
{
"extn_id": "signed_certificate_timestamp_list",
"critical": boolean,
"extn_value": string # [0]
}
Examples:
$ cat server.csr| jc --x509-csr -p
[
{
"certification_request_info": {
"version": "v1",
"subject": {
"common_name": "myserver.for.example"
},
"subject_pk_info": {
"algorithm": {
"algorithm": "ec",
"parameters": "secp256r1"
},
"public_key": "04:40:33:c0:91:8f:e9:46:ea:d0:dc:d0:f9:63:2..."
},
"attributes": [
{
"type": "extension_request",
"values": [
[
{
"extn_id": "extended_key_usage",
"critical": false,
"extn_value": [
"server_auth"
]
},
{
"extn_id": "subject_alt_name",
"critical": false,
"extn_value": [
"myserver.for.example"
]
}
]
]
}
]
},
"signature_algorithm": {
"algorithm": "sha384_ecdsa",
"parameters": null
},
"signature": "30:45:02:20:77:ac:5b:51:bf:c5:f5:43:02:52:ae:66:..."
}
]
$ openssl req -in server.csr | jc --x509-csr -p
[
{
"certification_request_info": {
"version": "v1",
"subject": {
"common_name": "myserver.for.example"
},
"subject_pk_info": {
"algorithm": {
"algorithm": "ec",
"parameters": "secp256r1"
},
"public_key": "04:40:33:c0:91:8f:e9:46:ea:d0:dc:d0:f9:63:2..."
},
"attributes": [
{
"type": "extension_request",
"values": [
[
{
"extn_id": "extended_key_usage",
"critical": false,
"extn_value": [
"server_auth"
]
},
{
"extn_id": "subject_alt_name",
"critical": false,
"extn_value": [
"myserver.for.example"
]
}
]
]
}
]
},
"signature_algorithm": {
"algorithm": "sha384_ecdsa",
"parameters": null
},
"signature": "30:45:02:20:77:ac:5b:51:bf:c5:f5:43:02:52:ae:66:..."
}
]
<a id="jc.parsers.x509_csr.parse"></a>
### parse
```python
def parse(data: Union[str, bytes],
raw: bool = False,
quiet: bool = False) -> List[Dict]
```
Main text parsing function
Parameters:
data: (string or bytes) text or binary data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -8,6 +8,7 @@ jc - JSON Convert `xrandr` command output parser
Usage (cli):
$ xrandr | jc --xrandr
$ xrandr --properties | jc --xrandr
or
@@ -49,13 +50,17 @@ Schema:
"is_connected": boolean,
"is_primary": boolean,
"device_name": string,
"model_name": string,
"product_id" string,
"serial_number": string,
"resolution_width": integer,
"resolution_height": integer,
"offset_width": integer,
"offset_height": integer,
"dimension_width": integer,
"dimension_height": integer,
"rotation": string
"rotation": string,
"reflection": string
}
],
"unassociated_devices": [
@@ -132,7 +137,71 @@ Examples:
"offset_height": 0,
"dimension_width": 310,
"dimension_height": 170,
"rotation": "normal"
"rotation": "normal",
"reflection": "normal"
}
}
],
"unassociated_devices": []
}
$ xrandr --properties | jc --xrandr -p
{
"screens": [
{
"screen_number": 0,
"minimum_width": 8,
"minimum_height": 8,
"current_width": 1920,
"current_height": 1080,
"maximum_width": 32767,
"maximum_height": 32767,
"associated_device": {
"associated_modes": [
{
"resolution_width": 1920,
"resolution_height": 1080,
"is_high_resolution": false,
"frequencies": [
{
"frequency": 60.03,
"is_current": true,
"is_preferred": true
},
{
"frequency": 59.93,
"is_current": false,
"is_preferred": false
}
]
},
{
"resolution_width": 1680,
"resolution_height": 1050,
"is_high_resolution": false,
"frequencies": [
{
"frequency": 59.88,
"is_current": false,
"is_preferred": false
}
]
}
],
"is_connected": true,
"is_primary": true,
"device_name": "eDP1",
"model_name": "ASUS VW193S",
"product_id": "54297",
"serial_number": "78L8021107",
"resolution_width": 1920,
"resolution_height": 1080,
"offset_width": 0,
"offset_height": 0,
"dimension_width": 310,
"dimension_height": 170,
"rotation": "normal",
"reflection": "normal"
}
}
],
@@ -162,4 +231,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, aix, freebsd
Version 1.1 by Kevin Lyter (lyter_git at sent.com)
Version 1.2 by Kevin Lyter (lyter_git at sent.com)

View File

@@ -18,8 +18,8 @@ Usage (module):
Schema:
YAML Document converted to a Dictionary
See https://pypi.org/project/ruamel.yaml for details
YAML Document converted to a Dictionary.
See https://pypi.org/project/ruamel.yaml for details.
[
{
@@ -30,7 +30,7 @@ Schema:
Examples:
$ cat istio-mtls-permissive.yaml
$ cat file.yaml
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
@@ -51,7 +51,7 @@ Examples:
tls:
mode: ISTIO_MUTUAL
$ cat istio-mtls-permissive.yaml | jc --yaml -p
$ cat file.yaml | jc --yaml -p
[
{
"apiVersion": "authentication.istio.io/v1alpha1",

View File

@@ -99,4 +99,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin
Version 1.1 by Matt J (https://github.com/listuser)
Version 1.2 by Matt J (https://github.com/listuser)

View File

@@ -0,0 +1,125 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.zpool_iostat"></a>
# jc.parsers.zpool\_iostat
jc - JSON Convert `zpool iostat` command output parser
Supports with or without the `-v` flag.
Usage (cli):
$ zpool iostat | jc --zpool-iostat
or
$ jc zpool iostat
Usage (module):
import jc
result = jc.parse('zpool_iostat', zpool_iostat_command_output)
Schema:
[
{
"pool": string,
"parent": string,
"cap_alloc": float,
"cap_alloc_unit": string,
"cap_free": float,
"cap_free_unit": string,
"ops_read": integer,
"ops_write": integer,
"bw_read": float,
"bw_read_unit": string,
"bw_write": float,
"bw_write_unit": string
}
]
Examples:
$ zpool iostat -v | jc --zpool-iostat -p
[
{
"pool": "zhgstera6",
"cap_alloc": 2.89,
"cap_free": 2.2,
"ops_read": 0,
"ops_write": 2,
"bw_read": 349.0,
"bw_write": 448.0,
"cap_alloc_unit": "T",
"cap_free_unit": "T",
"bw_read_unit": "K",
"bw_write_unit": "K"
},
{
"pool": "726060ALE614-K8JAPRGN:10",
"parent": "zhgstera6",
"cap_alloc": 2.89,
"cap_free": 2.2,
"ops_read": 0,
"ops_write": 2,
"bw_read": 349.0,
"bw_write": 448.0,
"cap_alloc_unit": "T",
"cap_free_unit": "T",
"bw_read_unit": "K",
"bw_write_unit": "K"
},
...
]
$ zpool iostat -v | jc --zpool-iostat -p -r
[
{
"pool": "zhgstera6",
"cap_alloc": "2.89T",
"cap_free": "2.20T",
"ops_read": "0",
"ops_write": "2",
"bw_read": "349K",
"bw_write": "448K"
},
{
"pool": "726060ALE614-K8JAPRGN:10",
"parent": "zhgstera6",
"cap_alloc": "2.89T",
"cap_free": "2.20T",
"ops_read": "0",
"ops_write": "2",
"bw_read": "349K",
"bw_write": "448K"
},
...
]
<a id="jc.parsers.zpool_iostat.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -0,0 +1,163 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.zpool_status"></a>
# jc.parsers.zpool\_status
jc - JSON Convert `zpool status` command output parser
Works with or without the `-v` option.
Usage (cli):
$ zpool status | jc --zpool-status
or
$ jc zpool status
Usage (module):
import jc
result = jc.parse('zpool_status', zpool_status_command_output)
Schema:
[
{
"pool": string,
"state": string,
"status": string,
"action": string,
"see": string,
"scan": string,
"scrub": string,
"config": [
{
"name": string,
"state": string,
"read": integer,
"write": integer,
"checksum": integer,
"errors": string,
}
],
"errors": string
}
]
Examples:
$ zpool status -v | jc --zpool-status -p
[
{
"pool": "tank",
"state": "DEGRADED",
"status": "One or more devices could not be opened. Suffic...",
"action": "Attach the missing device and online it using 'zpool...",
"see": "http://www.sun.com/msg/ZFS-8000-2Q",
"scrub": "none requested",
"config": [
{
"name": "tank",
"state": "DEGRADED",
"read": 0,
"write": 0,
"checksum": 0
},
{
"name": "mirror-0",
"state": "DEGRADED",
"read": 0,
"write": 0,
"checksum": 0
},
{
"name": "c1t0d0",
"state": "ONLINE",
"read": 0,
"write": 0,
"checksum": 0
},
{
"name": "c1t1d0",
"state": "UNAVAIL",
"read": 0,
"write": 0,
"checksum": 0,
"errors": "cannot open"
}
],
"errors": "No known data errors"
}
]
$ zpool status -v | jc --zpool-status -p -r
[
{
"pool": "tank",
"state": "DEGRADED",
"status": "One or more devices could not be opened. Sufficient...",
"action": "Attach the missing device and online it using 'zpool...",
"see": "http://www.sun.com/msg/ZFS-8000-2Q",
"scrub": "none requested",
"config": [
{
"name": "tank",
"state": "DEGRADED",
"read": "0",
"write": "0",
"checksum": "0"
},
{
"name": "mirror-0",
"state": "DEGRADED",
"read": "0",
"write": "0",
"checksum": "0"
},
{
"name": "c1t0d0",
"state": "ONLINE",
"read": "0",
"write": "0",
"checksum": "0"
},
{
"name": "c1t1d0",
"state": "UNAVAIL",
"read": "0",
"write": "0",
"checksum": "0",
"errors": "cannot open"
}
],
"errors": "No known data errors"
}
]
<a id="jc.parsers.zpool_status.parse"></a>
### parse
```python
def parse(data: str,
raw: bool = False,
quiet: bool = False) -> List[JSONDictType]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -51,7 +51,7 @@ Add `_jc_meta` object to output line if `ignore_exceptions=True`
### stream\_error
```python
def stream_error(e: BaseException, line: str) -> Dict[str, MetadataType]
def stream_error(e: BaseException, line: str) -> JSONDictType
```
Return an error `_jc_meta` field.

View File

@@ -91,7 +91,7 @@ Parameters:
the parser. compatible options:
linux, darwin, cygwin, win32, aix, freebsd
quiet: (bool) supress compatibility message if True
quiet: (bool) suppress compatibility message if True
Returns:
@@ -233,3 +233,6 @@ Returns a timestamp object with the following attributes:
utc (int | None): aware timestamp only if UTC timezone
detected in datetime string. None if conversion fails.
iso (str | None): ISO string - timezone information is output
only if UTC timezone is detected in the datetime string.

View File

@@ -124,6 +124,14 @@ Get a list of streaming parser module names to be used in
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
`parser_mod_list()`.
"""
from .lib import (__version__, parse, parser_mod_list, plugin_parser_mod_list,
standard_parser_mod_list, streaming_parser_mod_list,
parser_info, all_parser_info, get_help)
from .lib import (
__version__ as __version__,
parse as parse,
parser_mod_list as parser_mod_list,
plugin_parser_mod_list as plugin_parser_mod_list,
standard_parser_mod_list as standard_parser_mod_list,
streaming_parser_mod_list as streaming_parser_mod_list,
parser_info as parser_info,
all_parser_info as all_parser_info,
get_help as get_help
)

238
jc/cli.py
View File

@@ -5,17 +5,19 @@ JC cli module
import io
import sys
import os
import re
from itertools import islice
from datetime import datetime, timezone
import textwrap
import shlex
import subprocess
from typing import List, Union, Optional, TextIO
from typing import List, Dict, Iterable, Union, Optional, TextIO
from types import ModuleType
from .lib import (
__version__, parser_info, all_parser_info, parsers, _get_parser, _parser_is_streaming,
parser_mod_list, standard_parser_mod_list, plugin_parser_mod_list, streaming_parser_mod_list
)
from .jc_types import JSONDictType, AboutJCType, MetadataType, CustomColorType, ParserInfoType
from .jc_types import JSONDictType, CustomColorType, ParserInfoType
from . import utils
from .cli_data import (
long_options_map, new_pygments_colors, old_pygments_colors, helptext_preamble_string,
@@ -40,6 +42,10 @@ except Exception:
JC_CLEAN_EXIT: int = 0
JC_ERROR_EXIT: int = 100
MAX_EXIT: int = 255
SLICER_PATTERN: str = r'-?[0-9]*\:-?[0-9]*$'
SLICER_RE = re.compile(SLICER_PATTERN)
NEWLINES_PATTERN: str = r'(\r\n|\r|\n)'
NEWLINES_RE = re.compile(NEWLINES_PATTERN)
class info():
@@ -48,7 +54,7 @@ class info():
author: str = 'Kelly Brazil'
author_email: str = 'kellyjonbrazil@gmail.com'
website: str = 'https://github.com/kellyjonbrazil/jc'
copyright: str = '© 2019-2022 Kelly Brazil'
copyright: str = '© 2019-2023 Kelly Brazil'
license: str = 'MIT License'
@@ -64,17 +70,17 @@ if PYGMENTS_INSTALLED:
class JcCli():
__slots__ = (
'data_in', 'data_out', 'options', 'args', 'parser_module', 'parser_name', 'indent', 'pad',
'custom_colors', 'show_hidden', 'ascii_only', 'json_separators', 'json_indent',
'run_timestamp', 'about', 'debug', 'verbose_debug', 'force_color', 'mono', 'help_me',
'pretty', 'quiet', 'ignore_exceptions', 'raw', 'meta_out', 'unbuffer', 'version_info',
'yaml_output', 'bash_comp', 'zsh_comp', 'magic_found_parser', 'magic_options',
'magic_run_command', 'magic_run_command_str', 'magic_stdout', 'magic_stderr',
'magic_returncode'
'custom_colors', 'show_hidden', 'show_categories', 'ascii_only', 'json_separators',
'json_indent', 'run_timestamp', 'about', 'debug', 'verbose_debug', 'force_color', 'mono',
'help_me', 'pretty', 'quiet', 'ignore_exceptions', 'raw', 'meta_out', 'unbuffer',
'version_info', 'yaml_output', 'bash_comp', 'zsh_comp', 'magic_found_parser',
'magic_options', 'magic_run_command', 'magic_run_command_str', 'magic_stdout',
'magic_stderr', 'magic_returncode', 'slice_str', 'slice_start', 'slice_end'
)
def __init__(self) -> None:
self.data_in: Optional[Union[str, bytes, TextIO]] = None
self.data_out: Optional[Union[List[JSONDictType], JSONDictType, AboutJCType]] = None
self.data_in: Optional[Union[str, bytes, TextIO, Iterable[str]]] = None
self.data_out: Optional[Union[List[JSONDictType], JSONDictType]] = None
self.options: List[str] = []
self.args: List[str] = []
self.parser_module: Optional[ModuleType] = None
@@ -83,11 +89,17 @@ class JcCli():
self.pad: int = 0
self.custom_colors: CustomColorType = {}
self.show_hidden: bool = False
self.show_categories: bool = False
self.ascii_only: bool = False
self.json_separators: Optional[tuple[str, str]] = (',', ':')
self.json_indent: Optional[int] = None
self.run_timestamp: Optional[datetime] = None
# slicer
self.slice_str: str = ''
self.slice_start: Optional[int] = None
self.slice_end: Optional[int] = None
# cli options
self.about: bool = False
self.debug: bool = False
@@ -198,6 +210,41 @@ class JcCli():
return ptext
def parser_categories_text(self) -> str:
"""Return lists of parsers by category"""
category_text: str = ''
padding_char: str = ' '
all_parsers = all_parser_info(show_hidden=True, show_deprecated=False)
generic = [{'arg': x['argument'], 'desc': x['description']} for x in all_parsers if 'generic' in x.get('tags', [])]
standard = [{'arg': x['argument'], 'desc': x['description']} for x in all_parsers if 'standard' in x.get('tags', [])]
command = [{'arg': x['argument'], 'desc': x['description']} for x in all_parsers if 'command' in x.get('tags', [])]
file_str_bin = [
{'arg': x['argument'], 'desc': x['description']} for x in all_parsers
if 'file' in x.get('tags', []) or
'string' in x.get('tags', []) or
'binary' in x.get('tags', [])
]
streaming = [{'arg': x['argument'], 'desc': x['description']} for x in all_parsers if x.get('streaming')]
categories: Dict = {
'Generic Parsers:': generic,
'Standard Spec Parsers:': standard,
'File/String/Binary Parsers:': file_str_bin,
'Streaming Parsers:': streaming,
'Command Parsers:': command
}
for cat, cat_objs in categories.items():
category_text += f'{cat} ({len(cat_objs)})\n'
for p in cat_objs:
parser_arg: str = p.get('arg', 'UNKNOWN')
parser_desc: str = p.get('desc', 'No description available.')
padding: int = self.pad - len(parser_arg)
padding_text: str = padding_char * padding
category_text += f'{parser_arg}{padding_text}{parser_desc}\n'
category_text += '\n'
return category_text[:-1]
def options_text(self) -> str:
"""Return the argument and description information from each option"""
otext: str = ''
@@ -214,7 +261,7 @@ class JcCli():
return otext
@staticmethod
def about_jc() -> AboutJCType:
def about_jc() -> JSONDictType:
"""Return jc info and the contents of each parser.info as a dictionary"""
return {
'name': 'jc',
@@ -236,8 +283,6 @@ class JcCli():
def helptext(self) -> str:
"""Return the help text with the list of parsers"""
self.indent = 4
self.pad = 20
parsers_string: str = self.parsers_text()
options_string: str = self.options_text()
helptext_string: str = f'{helptext_preamble_string}{parsers_string}\nOptions:\n{options_string}\n{helptext_end_string}'
@@ -248,6 +293,13 @@ class JcCli():
Pages the parser documentation if a parser is found in the arguments,
otherwise the general help text is printed.
"""
self.indent = 4
self.pad = 22
if self.show_categories:
utils._safe_print(self.parser_categories_text())
return
for arg in self.args:
parser_name: str = self.parser_shortname(arg)
@@ -391,6 +443,17 @@ class JcCli():
self.magic_options = []
return
# slicer found
if ':' in arg:
if SLICER_RE.match(arg):
self.slice_str = arg
args_given.pop(0)
continue
else:
utils.warning_message(['Invalid slice syntax.'])
args_given.pop(0)
continue
# option found - populate option list
if arg.startswith('-'):
self.magic_options.extend(args_given.pop(0)[1:])
@@ -533,9 +596,108 @@ class JcCli():
utils.error_message(['Missing piped data. Use "jc -h" for help.'])
self.exit_error()
def add_metadata_to_output(self) -> None:
"""
This function mutates data_out in place. If the _jc_meta field
does not already exist, it will be created with the metadata fields. If
the _jc_meta field already exists, the metadata fields will be added to
the existing object.
In the case of an empty list (no data), a dictionary with a _jc_meta
object will be added to the list. This way you always get metadata,
even if there are no results.
"""
if self.run_timestamp:
meta_obj: JSONDictType = {
'parser': self.parser_name,
'timestamp': self.run_timestamp.timestamp(),
'slice_start': self.slice_start,
'slice_end': self.slice_end
}
if self.magic_run_command:
meta_obj['magic_command'] = self.magic_run_command
meta_obj['magic_command_exit'] = self.magic_returncode
if isinstance(self.data_out, dict):
if '_jc_meta' not in self.data_out:
self.data_out['_jc_meta'] = {}
self.data_out['_jc_meta'].update(meta_obj)
elif isinstance(self.data_out, list):
if not self.data_out:
self.data_out.append({})
for item in self.data_out:
if isinstance(item, dict):
if '_jc_meta' not in item:
item['_jc_meta'] = {}
item['_jc_meta'].update(meta_obj)
else:
utils.error_message(['Parser returned an unsupported object type.'])
self.exit_error()
@staticmethod
def lazy_splitlines(text: str) -> Iterable[str]:
start = 0
for m in NEWLINES_RE.finditer(text):
begin, end = m.span()
if begin != start:
yield text[start:begin]
start = end
if text[start:]:
yield text[start:]
def slicer(self) -> None:
"""Slice input data lazily, if possible. Updates self.data_in"""
if self.slice_str:
slice_start_str, slice_end_str = self.slice_str.split(':', maxsplit=1)
if slice_start_str:
self.slice_start = int(slice_start_str)
if slice_end_str:
self.slice_end = int(slice_end_str)
if not self.slice_start is None or not self.slice_end is None:
# standard parsers UTF-8 input
if isinstance(self.data_in, str):
data_in_iter = self.lazy_splitlines(self.data_in)
# positive slices
if (self.slice_start is None or self.slice_start >= 0) \
and (self.slice_end is None or self.slice_end >= 0):
self.data_in = '\n'.join(islice(data_in_iter, self.slice_start, self.slice_end))
# negative slices found (non-lazy, uses more memory)
else:
self.data_in = '\n'.join(list(data_in_iter)[self.slice_start:self.slice_end])
# standard parsers bytes input
elif isinstance(self.data_in, bytes):
utils.warning_message(['Cannot slice bytes data.'])
# streaming parsers UTF-8 input
else:
# positive slices
if (self.slice_start is None or self.slice_start >= 0) \
and (self.slice_end is None or self.slice_end >= 0) \
and self.data_in:
self.data_in = islice(self.data_in, self.slice_start, self.slice_end)
# negative slices found (non-lazy, uses more memory)
elif self.data_in:
self.data_in = list(self.data_in)[self.slice_start:self.slice_end]
def streaming_parse_and_print(self) -> None:
"""only supports UTF-8 string data for now"""
self.data_in = sys.stdin
self.slicer()
if self.parser_module:
result = self.parser_module.parse(
self.data_in,
@@ -563,6 +725,8 @@ class JcCli():
except UnicodeDecodeError:
pass
self.slicer()
if self.parser_module:
self.data_out = self.parser_module.parse(
self.data_in,
@@ -586,48 +750,6 @@ class JcCli():
exit_code = min(exit_code, MAX_EXIT)
sys.exit(exit_code)
def add_metadata_to_output(self) -> None:
"""
This function mutates data_out in place. If the _jc_meta field
does not already exist, it will be created with the metadata fields. If
the _jc_meta field already exists, the metadata fields will be added to
the existing object.
In the case of an empty list (no data), a dictionary with a _jc_meta
object will be added to the list. This way you always get metadata,
even if there are no results.
"""
if self.run_timestamp:
meta_obj: MetadataType = {
'parser': self.parser_name,
'timestamp': self.run_timestamp.timestamp()
}
if self.magic_run_command:
meta_obj['magic_command'] = self.magic_run_command
meta_obj['magic_command_exit'] = self.magic_returncode
if isinstance(self.data_out, dict):
if '_jc_meta' not in self.data_out:
self.data_out['_jc_meta'] = {} # type: ignore
self.data_out['_jc_meta'].update(meta_obj) # type: ignore
elif isinstance(self.data_out, list):
if not self.data_out:
self.data_out.append({})
for item in self.data_out:
if isinstance(item, dict):
if '_jc_meta' not in item:
item['_jc_meta'] = {}
item['_jc_meta'].update(meta_obj) # type: ignore
else:
utils.error_message(['Parser returned an unsupported object type.'])
self.exit_error()
def _run(self) -> None:
# enable colors for Windows cmd.exe terminal
if sys.platform.startswith('win32'):
@@ -643,6 +765,9 @@ class JcCli():
# find options if magic_parser did not find a command
if not self.magic_found_parser:
for opt in self.args:
if SLICER_RE.match(opt):
self.slice_str = opt
if opt in long_options_map:
self.options.extend(long_options_map[opt][0])
@@ -655,6 +780,7 @@ class JcCli():
self.force_color = 'C' in self.options
self.help_me = 'h' in self.options
self.show_hidden = self.options.count('h') > 1 # verbose help
self.show_categories = self.options.count('h') > 2
self.pretty = 'p' in self.options
self.quiet = 'q' in self.options
self.ignore_exceptions = self.options.count('q') > 1

View File

@@ -3,7 +3,7 @@ from typing import List, Dict
long_options_map: Dict[str, List[str]] = {
'--about': ['a', 'about jc'],
'--force-color': ['C', 'force color output even when using pipes (overrides -m)'],
'--force-color': ['C', 'force color output (overrides -m)'],
'--debug': ['d', 'debug (double for verbose debug)'],
'--help': ['h', 'help (--help --parser_name for parser documentation)'],
'--monochrome': ['m', 'monochrome output'],
@@ -63,17 +63,17 @@ Usage:
Standard syntax:
COMMAND | jc [OPTIONS] PARSER
COMMAND | jc [SLICE] [OPTIONS] PARSER
cat FILE | jc [OPTIONS] PARSER
cat FILE | jc [SLICE] [OPTIONS] PARSER
echo STRING | jc [OPTIONS] PARSER
echo STRING | jc [SLICE] [OPTIONS] PARSER
Magic syntax:
jc [OPTIONS] COMMAND
jc [SLICE] [OPTIONS] COMMAND
jc [OPTIONS] /proc/<path-to-procfile>
jc [SLICE] [OPTIONS] /proc/<path-to-procfile>
Parsers:
'''
@@ -88,9 +88,13 @@ Examples:
$ jc --pretty dig www.google.com
$ jc --pretty /proc/meminfo
Line Slicing:
$ cat file.csv | jc :101 --csv # parse first 100 lines
Parser Documentation:
$ jc --help --dig
Show Hidden Parsers:
$ jc -hh
More Help:
$ jc -hh # show hidden parsers
$ jc -hhh # list parsers by category tags
'''

View File

@@ -1,11 +1,9 @@
"""jc - JSON Convert lib module"""
import sys
from datetime import datetime
from typing import Dict, List, Tuple, Iterator, Optional, Union
from typing import Any, Dict, List, Tuple, Iterator, Optional, Union
JSONDictType = Dict[str, Union[str, int, float, bool, List, Dict, None]]
MetadataType = Dict[str, Optional[Union[str, int, float, List[str], datetime]]]
JSONDictType = Dict[str, Any]
StreamingOutputType = Iterator[Union[JSONDictType, Tuple[BaseException, str]]]
if sys.version_info >= (3, 8):
@@ -22,6 +20,7 @@ if sys.version_info >= (3, 8):
"author_email": str,
"compatible": List[str],
"magic_commands": List[str],
"tags": List[str],
"documentation": str,
"streaming": bool,
"plugin": bool,
@@ -45,9 +44,6 @@ else:
TimeStampFormatType = Dict
AboutJCType = Dict[str, Union[str, int, List[ParserInfoType]]]
try:
from pygments.token import (Name, Number, String, Keyword)
CustomColorType = Dict[Union[Name.Tag, Number, String, Keyword], str]

View File

@@ -3,13 +3,13 @@ import sys
import os
import re
import importlib
from typing import List, Iterable, Union, Iterator
from typing import List, Iterable, Optional, Union, Iterator
from types import ModuleType
from .jc_types import ParserInfoType, JSONDictType
from jc import appdirs
__version__ = '1.22.2'
__version__ = '1.23.3'
parsers: List[str] = [
'acpi',
@@ -19,10 +19,15 @@ parsers: List[str] = [
'asciitable',
'asciitable-m',
'blkid',
'bluetoothctl',
'cbt',
'cef',
'cef-s',
'certbot',
'chage',
'cksum',
'clf',
'clf-s',
'crontab',
'crontab-u',
'csv',
@@ -56,12 +61,14 @@ parsers: List[str] = [
'id',
'ifconfig',
'ini',
'ini-dup',
'iostat',
'iostat-s',
'ip-address',
'iptables',
'iso-datetime',
'iw-scan',
'iwconfig',
'jar-manifest',
'jobs',
'jwt',
@@ -69,6 +76,7 @@ parsers: List[str] = [
'last',
'ls',
'ls-s',
'lsattr',
'lsblk',
'lsmod',
'lsof',
@@ -82,9 +90,11 @@ parsers: List[str] = [
'netstat',
'nmcli',
'ntpq',
'openvpn',
'os-prober',
'passwd',
'pci-ids',
'pgpass',
'pidstat',
'pidstat-s',
'ping',
@@ -151,7 +161,9 @@ parsers: List[str] = [
'semver',
'sfdisk',
'shadow',
'srt',
'ss',
'ssh-conf',
'sshd-conf',
'stat',
'stat-s',
@@ -168,6 +180,7 @@ parsers: List[str] = [
'time',
'timedatectl',
'timestamp',
'toml',
'top',
'top-s',
'tracepath',
@@ -181,16 +194,21 @@ parsers: List[str] = [
'upower',
'uptime',
'url',
'ver',
'veracrypt',
'vmstat',
'vmstat-s',
'w',
'wc',
'who',
'x509-cert',
'x509-csr',
'xml',
'xrandr',
'yaml',
'zipinfo'
'zipinfo',
'zpool-iostat',
'zpool-status'
]
def _cliname_to_modname(parser_cli_name: str) -> str:
@@ -201,6 +219,19 @@ def _modname_to_cliname(parser_mod_name: str) -> str:
"""Return module's cli name (underscores converted to dashes)"""
return parser_mod_name.replace('_', '-')
def _is_valid_parser_plugin(name: str, local_parsers_dir: str) -> bool:
if re.match(r'\w+\.py$', name) and os.path.isfile(os.path.join(local_parsers_dir, name)):
try:
parser_mod_name = _cliname_to_modname(name)[0:-3]
modpath = 'jcparsers.'
plugin = importlib.import_module(f'{modpath}{parser_mod_name}')
if hasattr(plugin, 'info') and hasattr(plugin, 'parse'):
del plugin
return True
except Exception:
return False
return False
# Create the local_parsers list. This is a list of custom or
# override parsers from <user_data_dir>/jc/jcparsers/*.py.
# Once this list is created, extend the parsers list with it.
@@ -210,7 +241,7 @@ local_parsers_dir = os.path.join(data_dir, 'jcparsers')
if os.path.isdir(local_parsers_dir):
sys.path.append(data_dir)
for name in os.listdir(local_parsers_dir):
if re.match(r'\w+\.py$', name) and os.path.isfile(os.path.join(local_parsers_dir, name)):
if _is_valid_parser_plugin(name, local_parsers_dir):
plugin_name = name[0:-3]
local_parsers.append(_modname_to_cliname(plugin_name))
if plugin_name not in parsers:
@@ -271,7 +302,7 @@ def parse(
data: Union[str, bytes, Iterable[str]],
quiet: bool = False,
raw: bool = False,
ignore_exceptions: bool = None,
ignore_exceptions: Optional[bool] = None,
**kwargs
) -> Union[JSONDictType, List[JSONDictType], Iterator[JSONDictType]]:
"""

View File

@@ -227,12 +227,13 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.4'
version = '1.6'
description = '`acpi` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['acpi']
tags = ['command']
__version__ = info.version
@@ -332,10 +333,19 @@ def parse(data, raw=False, quiet=False):
if obj_type == 'Battery':
output_line['type'] = obj_type
output_line['id'] = obj_id
if 'Charging' in line or 'Discharging' in line or 'Full' in line:
if 'Not charging' in line:
output_line['state'] = 'Not charging'
output_line['charge_percent'] = line.split()[-1].rstrip('%,')
if 'Charging' in line \
or 'Discharging' in line \
or 'Full' in line:
output_line['state'] = line.split()[2][:-1]
output_line['charge_percent'] = line.split()[3].rstrip('%,')
if 'rate information unavailable' not in line:
if 'will never fully discharge' in line:
pass
elif 'rate information unavailable' not in line:
if 'Charging' in line:
output_line['until_charged'] = line.split()[4]
if 'Discharging' in line:

View File

@@ -86,6 +86,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['darwin']
magic_commands = ['airport -I']
tags = ['command']
__version__ = info.version

View File

@@ -115,6 +115,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['darwin']
magic_commands = ['airport -s']
tags = ['command']
__version__ = info.version

View File

@@ -119,12 +119,13 @@ import jc.parsers.universal
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.11'
version = '1.12'
description = '`arp` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['arp']
tags = ['command']
__version__ = info.version
@@ -221,14 +222,26 @@ def parse(
else:
for line in cleandata:
splitline = line.split()
if '<incomplete>' not in splitline:
# Ignore AIX bucket information
if 'bucket:' in splitline[0]:
continue
elif 'There' in splitline[0] and 'are' in splitline[1]:
continue
# AIX uses (incomplete)
elif '<incomplete>' not in splitline and '(incomplete)' not in splitline:
output_line = {
'name': splitline[0],
'address': splitline[1].lstrip('(').rstrip(')'),
'hwtype': splitline[4].lstrip('[').rstrip(']'),
'hwaddress': splitline[3],
'iface': splitline[6],
}
# Handle permanence and ignore interface in AIX
if 'permanent' in splitline:
output_line['permanent'] = True
elif 'in' not in splitline[6]: # AIX doesn't show interface
output_line['iface'] = splitline[6]
else:
output_line = {
@@ -236,8 +249,10 @@ def parse(
'address': splitline[1].lstrip('(').rstrip(')'),
'hwtype': None,
'hwaddress': None,
'iface': splitline[5],
}
# AIX doesn't show interface
if len(splitline) >= 5:
output_line['iface'] = splitline[5]
raw_output.append(output_line)

View File

@@ -130,6 +130,7 @@ class info():
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['generic', 'string']
__version__ = info.version

View File

@@ -115,6 +115,7 @@ class info():
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['generic', 'string']
__version__ = info.version

View File

@@ -567,7 +567,7 @@ class DSASignature(Sequence):
@classmethod
def from_p1363(cls, data):
"""
Reads a signature from a byte string encoding accordint to IEEE P1363,
Reads a signature from a byte string encoding according to IEEE P1363,
which is used by Microsoft's BCryptSignHash() function.
:param data:

View File

@@ -247,7 +247,7 @@ class Asn1Value(object):
:param no_explicit:
If explicit tagging info should be removed from this instance.
Used internally to allow contructing the underlying value that
Used internally to allow constructing the underlying value that
has been wrapped in an explicit tag.
:param tag_type:
@@ -697,7 +697,7 @@ class Castable(object):
if other_class.tag != self.__class__.tag:
raise TypeError(unwrap(
'''
Can not covert a value from %s object to %s object since they
Can not convert a value from %s object to %s object since they
use different tags: %d versus %d
''',
type_name(other_class),
@@ -1349,7 +1349,7 @@ class Choice(Asn1Value):
class Concat(object):
"""
A class that contains two or more encoded child values concatentated
A class that contains two or more encoded child values concatenated
together. THIS IS NOT PART OF THE ASN.1 SPECIFICATION! This exists to handle
the x509.TrustedCertificate() class for OpenSSL certificates containing
extra information.
@@ -3757,7 +3757,7 @@ class Sequence(Asn1Value):
def _make_value(self, field_name, field_spec, value_spec, field_params, value):
"""
Contructs an appropriate Asn1Value object for a field
Constructs an appropriate Asn1Value object for a field
:param field_name:
A unicode string of the field name
@@ -3766,7 +3766,7 @@ class Sequence(Asn1Value):
An Asn1Value class that is the field spec
:param value_spec:
An Asn1Value class that is the vaue spec
An Asn1Value class that is the value spec
:param field_params:
None or a dict of params for the field spec

View File

@@ -0,0 +1 @@
quiet = False

View File

@@ -251,7 +251,18 @@ class EmailAddress(IA5String):
self._unicode = contents.decode('cp1252')
else:
mailbox, hostname = contents.rsplit(b'@', 1)
self._unicode = mailbox.decode('cp1252') + '@' + hostname.decode('idna')
# fix to allow incorrectly encoded email addresses to succeed with warning
try:
self._unicode = mailbox.decode('cp1252') + '@' + hostname.decode('idna')
except UnicodeDecodeError:
ascii_mailbox = mailbox.decode('ascii', errors='backslashreplace')
ascii_hostname = hostname.decode('ascii', errors='backslashreplace')
from jc.utils import warning_message
import jc.parsers.asn1crypto.jc_global as jc_global
if not jc_global.quiet:
warning_message([f'Invalid email address found: {ascii_mailbox}@{ascii_hostname}'])
self._unicode = ascii_mailbox + '@' + ascii_hostname
return self._unicode
def __ne__(self, other):

View File

@@ -127,6 +127,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['blkid']
tags = ['command']
__version__ = info.version

421
jc/parsers/bluetoothctl.py Normal file
View File

@@ -0,0 +1,421 @@
"""jc - JSON Convert `bluetoothctl` command output parser
Supports the following `bluetoothctl` subcommands:
- `bluetoothctl list`
- `bluetoothctl show`
- `bluetoothctl show <ctrl>`
- `bluetoothctl devices`
- `bluetoothctl info <dev>`
Usage (cli):
$ bluetoothctl info <dev> | jc --bluetoothctl
or
$ jc bluetoothctl info <dev>
Usage (module):
import jc
result = jc.parse('bluetoothctl', bluetoothctl_command_output)
Schema:
Because bluetoothctl is handling two main entities, controllers and devices,
the schema is shared between them. Most of the fields are common between
a controller and a device but there might be fields corresponding to one entity.
Controller:
[
{
"name": string,
"is_default": boolean,
"is_public": boolean,
"is_random": boolean,
"address": string,
"alias": string,
"class": string,
"powered": string,
"discoverable": string,
"discoverable_timeout": string,
"pairable": string,
"modalias": string,
"discovering": string,
"uuids": array
}
]
Device:
[
{
"name": string,
"is_public": boolean,
"is_random": boolean,
"address": string,
"alias": string,
"appearance": string,
"class": string,
"icon": string,
"paired": string,
"bonded": string,
"trusted": string,
"blocked": string,
"connected": string,
"legacy_pairing": string,
"rssi": int,
"txpower": int,
"uuids": array,
"modalias": string
}
]
Examples:
$ bluetoothctl info EB:06:EF:62:B3:19 | jc --bluetoothctl -p
[
{
"address": "22:06:33:62:B3:19",
"is_public": true,
"name": "TaoTronics TT-BH336",
"alias": "TaoTronics TT-BH336",
"class": "0x00240455",
"icon": "audio-headset",
"paired": "no",
"bonded": "no",
"trusted": "no",
"blocked": "no",
"connected": "no",
"legacy_pairing": "no",
"uuids": [
"Advanced Audio Distribu.. (0000120d-0000-1000-8000-00805f9b34fb)",
"Audio Sink (0000130b-0000-1000-8000-00805f9b34fb)",
"A/V Remote Control (0000140e-0000-1000-8000-00805f9b34fb)",
"A/V Remote Control Cont.. (0000150f-0000-1000-8000-00805f9b34fb)",
"Handsfree (0000161e-0000-1000-8000-00805f9b34fb)",
"Headset (00001708-0000-1000-8000-00805f9b34fb)",
"Headset HS (00001831-0000-1000-8000-00805f9b34fb)"
],
"rssi": -52,
"txpower": 4
}
]
"""
import re
from typing import List, Dict, Optional, Any
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.1'
description = '`bluetoothctl` command parser'
author = 'Jake Ob'
author_email = 'iakopap at gmail.com'
compatible = ['linux']
magic_commands = ['bluetoothctl']
tags = ['command']
__version__ = info.version
try:
from typing import TypedDict
Controller = TypedDict(
"Controller",
{
"name": str,
"is_default": bool,
"is_public": bool,
"is_random": bool,
"address": str,
"alias": str,
"class": str,
"powered": str,
"discoverable": str,
"discoverable_timeout": str,
"pairable": str,
"modalias": str,
"discovering": str,
"uuids": List[str],
},
)
Device = TypedDict(
"Device",
{
"name": str,
"is_public": bool,
"is_random": bool,
"address": str,
"alias": str,
"appearance": str,
"class": str,
"icon": str,
"paired": str,
"bonded": str,
"trusted": str,
"blocked": str,
"connected": str,
"legacy_pairing": str,
"rssi": int,
"txpower": int,
"uuids": List[str],
"modalias": str
},
)
except ImportError:
Controller = Dict[str, Any] # type: ignore
Device = Dict[str, Any] # type: ignore
_controller_head_pattern = r"Controller (?P<address>([0-9A-F]{2}:){5}[0-9A-F]{2}) (?P<name>.+)"
_controller_line_pattern = (
r"(\s*Name:\s*(?P<name>.+)"
+ r"|\s*Alias:\s*(?P<alias>.+)"
+ r"|\s*Class:\s*(?P<class>.+)"
+ r"|\s*Powered:\s*(?P<powered>.+)"
+ r"|\s*Discoverable:\s*(?P<discoverable>.+)"
+ r"|\s*DiscoverableTimeout:\s*(?P<discoverable_timeout>.+)"
+ r"|\s*Pairable:\s*(?P<pairable>.+)"
+ r"|\s*Modalias:\s*(?P<modalias>.+)"
+ r"|\s*Discovering:\s*(?P<discovering>.+)"
+ r"|\s*UUID:\s*(?P<uuid>.+))"
)
def _parse_controller(next_lines: List[str]) -> Optional[Controller]:
next_line = next_lines.pop()
result = re.match(_controller_head_pattern, next_line)
if not result:
next_lines.append(next_line)
return None
matches = result.groupdict()
name = matches["name"]
if name.endswith("not available"):
return None
controller: Controller = {
"name": '',
"is_default": False,
"is_public": False,
"is_random": False,
"address": matches["address"],
"alias": '',
"class": '',
"powered": '',
"discoverable": '',
"discoverable_timeout": '',
"pairable": '',
"modalias": '',
"discovering": '',
"uuids": [],
}
if name.endswith("[default]"):
controller["is_default"] = True
name = name.replace("[default]", "")
elif name.endswith("(public)"):
controller["is_public"] = True
name = name.replace("(public)", "")
elif name.endswith("(random)"):
controller["is_random"] = True
name = name.replace("(random)", "")
controller["name"] = name.strip()
while next_lines:
next_line = next_lines.pop()
result = re.match(_controller_line_pattern, next_line)
if not result:
next_lines.append(next_line)
return controller
matches = result.groupdict()
if matches["name"]:
controller["name"] = matches["name"]
elif matches["alias"]:
controller["alias"] = matches["alias"]
elif matches["class"]:
controller["class"] = matches["class"]
elif matches["powered"]:
controller["powered"] = matches["powered"]
elif matches["discoverable"]:
controller["discoverable"] = matches["discoverable"]
elif matches["discoverable_timeout"]:
controller["discoverable_timeout"] = matches["discoverable_timeout"]
elif matches["pairable"]:
controller["pairable"] = matches["pairable"]
elif matches["modalias"]:
controller["modalias"] = matches["modalias"]
elif matches["discovering"]:
controller["discovering"] = matches["discovering"]
elif matches["uuid"]:
if not "uuids" in controller:
controller["uuids"] = []
controller["uuids"].append(matches["uuid"])
return controller
_device_head_pattern = r"Device (?P<address>([0-9A-F]{2}:){5}[0-9A-F]{2}) (?P<name>.+)"
_device_line_pattern = (
r"(\s*Name:\s*(?P<name>.+)"
+ r"|\s*Alias:\s*(?P<alias>.+)"
+ r"|\s*Appearance:\s*(?P<appearance>.+)"
+ r"|\s*Class:\s*(?P<class>.+)"
+ r"|\s*Icon:\s*(?P<icon>.+)"
+ r"|\s*Paired:\s*(?P<paired>.+)"
+ r"|\s*Bonded:\s*(?P<bonded>.+)"
+ r"|\s*Trusted:\s*(?P<trusted>.+)"
+ r"|\s*Blocked:\s*(?P<blocked>.+)"
+ r"|\s*Connected:\s*(?P<connected>.+)"
+ r"|\s*LegacyPairing:\s*(?P<legacy_pairing>.+)"
+ r"|\s*Modalias:\s*(?P<modalias>.+)"
+ r"|\s*RSSI:\s*(?P<rssi>.+)"
+ r"|\s*TxPower:\s*(?P<txpower>.+)"
+ r"|\s*UUID:\s*(?P<uuid>.+))"
)
def _parse_device(next_lines: List[str], quiet: bool) -> Optional[Device]:
next_line = next_lines.pop()
result = re.match(_device_head_pattern, next_line)
if not result:
next_lines.append(next_line)
return None
matches = result.groupdict()
name = matches["name"]
if name.endswith("not available"):
return None
device: Device = {
"name": '',
"is_public": False,
"is_random": False,
"address": matches["address"],
"alias": '',
"appearance": '',
"class": '',
"icon": '',
"paired": '',
"bonded": '',
"trusted": '',
"blocked": '',
"connected": '',
"legacy_pairing": '',
"rssi": 0,
"txpower": 0,
"uuids": [],
"modalias": ''
}
if name.endswith("(public)"):
device["is_public"] = True
name = name.replace("(public)", "")
elif name.endswith("(random)"):
device["is_random"] = True
name = name.replace("(random)", "")
device["name"] = name.strip()
while next_lines:
next_line = next_lines.pop()
result = re.match(_device_line_pattern, next_line)
if not result:
next_lines.append(next_line)
return device
matches = result.groupdict()
if matches["name"]:
device["name"] = matches["name"]
elif matches["alias"]:
device["alias"] = matches["alias"]
elif matches["appearance"]:
device["appearance"] = matches["appearance"]
elif matches["class"]:
device["class"] = matches["class"]
elif matches["icon"]:
device["icon"] = matches["icon"]
elif matches["paired"]:
device["paired"] = matches["paired"]
elif matches["bonded"]:
device["bonded"] = matches["bonded"]
elif matches["trusted"]:
device["trusted"] = matches["trusted"]
elif matches["blocked"]:
device["blocked"] = matches["blocked"]
elif matches["connected"]:
device["connected"] = matches["connected"]
elif matches["legacy_pairing"]:
device["legacy_pairing"] = matches["legacy_pairing"]
elif matches["rssi"]:
rssi = matches["rssi"]
try:
device["rssi"] = int(rssi)
except ValueError:
if not quiet:
jc.utils.warning_message([f"{next_line} : rssi - {rssi} is not int-able"])
elif matches["txpower"]:
txpower = matches["txpower"]
try:
device["txpower"] = int(txpower)
except ValueError:
if not quiet:
jc.utils.warning_message([f"{next_line} : txpower - {txpower} is not int-able"])
elif matches["uuid"]:
if not "uuids" in device:
device["uuids"] = []
device["uuids"].append(matches["uuid"])
elif matches["modalias"]:
device["modalias"] = matches["modalias"]
return device
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[JSONDictType]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
result: List = []
if jc.utils.has_data(data):
linedata = data.splitlines()
linedata.reverse()
while linedata:
element = None
if data.startswith("Controller"):
element = _parse_controller(linedata)
elif data.startswith("Device"):
element = _parse_device(linedata, quiet) # type: ignore
if element:
result.append(element)
else:
break
return result

195
jc/parsers/cbt.py Normal file
View File

@@ -0,0 +1,195 @@
"""jc - JSON Convert `cbt` command output parser (Google Bigtable)
Parses the human-, but not machine-, friendly output of the cbt command (for
Google's Bigtable).
No effort is made to convert the data types of the values in the cells.
The `timestamp_epoch` calculated timestamp field is naive. (i.e. based on
the local time of the system the parser is run on)
The `timestamp_epoch_utc` calculated timestamp field is timezone-aware and
is only available if the timestamp has a UTC timezone.
The `timestamp_iso` calculated timestamp field will only include UTC
timezone information if the timestamp has a UTC timezone.
Raw output contains all cells for each column (including timestamps), while
the normal output contains only the latest value for each column.
Usage (cli):
$ cbt | jc --cbt
or
$ jc cbt
Usage (module):
import jc
result = jc.parse('cbt', cbt_command_output)
Schema:
[
{
"key": string,
"cells": {
<string>: { # column family
<string>: string # column: value
}
}
}
]
Schema (raw):
[
{
"key": string,
"cells": [
{
"column_family": string,
"column": string,
"value": string,
"timestamp_iso": string,
"timestamp_epoch": integer,
"timestamp_epoch_utc": integer
}
]
}
]
Examples:
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p
[
{
"key": "foo",
"cells": {
"foo": {
"bar": "baz"
}
}
}
]
$ cbt -project=$PROJECT -instance=$INSTANCE lookup $TABLE foo | jc --cbt -p -r
[
{
"key": "foo",
"cells": [
{
"column_family": "foo",
"column": "bar",
"value": "baz1",
"timestamp_iso": "1970-01-01T01:00:00",
"timestamp_epoch": 32400,
"timestamp_epoch_utc": null
}
]
}
]
"""
from itertools import groupby
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`cbt` (Google Bigtable) command parser'
author = 'Andreas Weiden'
author_email = 'andreas.weiden@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
magic_commands = ['cbt']
tags = ['command']
__version__ = info.version
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
out_data = []
for row in proc_data:
cells: Dict = {}
key_func = lambda cell: (cell["column_family"], cell["column"])
all_cells = sorted(row["cells"], key=key_func)
for (column_family, column), group in groupby(all_cells, key=key_func):
group_list = sorted(group, key=lambda cell: cell["timestamp_iso"], reverse=True)
if column_family not in cells:
cells[column_family] = {}
cells[column_family][column] = group_list[0]["value"]
row["cells"] = cells
out_data.append(row)
return out_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[JSONDictType]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List[Dict] = []
if jc.utils.has_data(data):
for line in filter(None, data.split("-" * 40)):
key = None
cells = []
column_name = ""
timestamp = ""
value_next = False
for field in line.splitlines():
if not field.strip():
continue
if field.startswith(" " * 4):
value = field.strip(' "')
if value_next:
dt = jc.utils.timestamp(timestamp, format_hint=(1750, 1755))
cells.append({
"column_family": column_name.split(":", 1)[0],
"column": column_name.split(":", 1)[1],
"value": value,
"timestamp_iso": dt.iso,
"timestamp_epoch": dt.naive,
"timestamp_epoch_utc": dt.utc
})
elif field.startswith(" " * 2):
column_name, timestamp = map(str.strip, field.split("@"))
value_next = True
else:
key = field
if key is not None:
raw_output.append({"key": key, "cells": cells})
return raw_output if raw else _process(raw_output)

View File

@@ -129,6 +129,8 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the pycef library at https://github.com/DavidJBianco/pycef/releases/tag/v1.11-2'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
__version__ = info.version
@@ -185,7 +187,7 @@ def _pycef_parse(str_input):
# If the input entry had any blanks in the required headers, that's wrong
# and we should return. Note we explicitly don't check the last item in the
# split list becuase the header ends in a '|' which means the last item
# split list because the header ends in a '|' which means the last item
# will always be an empty string (it doesn't exist, but the delimiter does).
if "" in spl[0:-1]:
raise ParseError('Blank field(s) in CEF header. Is it valid CEF format?')

View File

@@ -103,6 +103,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the pycef library at https://github.com/DavidJBianco/pycef/releases/tag/v1.11-2'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
streaming = True

263
jc/parsers/certbot.py Normal file
View File

@@ -0,0 +1,263 @@
"""jc - JSON Convert `certbot` command output parser
Supports the following `certbot` commands:
- `certbot show_account`
- `certbot certificates`
Verbose options are not supported.
Usage (cli):
$ certbot show_account | jc --certbot
$ certbot certificates | jc --certbot
or
$ jc certbot show_account
$ jc certbot certificates
Usage (module):
import jc
result = jc.parse('certbot', certbot_command_output)
Schema:
{
"certificates": [
{
"name": string,
"serial_number": string,
"key_type": string,
"domains": [
string
],
"expiration_date": string,
"expiration_date_epoch": integer,
"expiration_date_epoch_utc": integer,
"expiration_date_iso": string,
"validity": string,
"certificate_path": string,
"private_key_path": string
}
],
"account": {
"server": string,
"url": string,
"email": string
}
}
Examples:
$ certbot certificates | jc --certbot -p
{
"certificates": [
{
"name": "example.com",
"serial_number": "3f7axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"key_type": "RSA",
"domains": [
"example.com",
"www.example.com"
],
"expiration_date": "2023-05-11 01:33:10+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.com/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.com/priv.pem",
"expiration_date_epoch": 1683793990,
"expiration_date_epoch_utc": 1683768790,
"expiration_date_iso": "2023-05-11T01:33:10+00:00"
},
{
"name": "example.org",
"serial_number": "3bcyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"key_type": "RSA",
"domains": [
"example.org",
"www.example.org"
],
"expiration_date": "2023-06-12 01:35:30+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.org/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.org/key.pem",
"expiration_date_epoch": 1686558930,
"expiration_date_epoch_utc": 1686533730,
"expiration_date_iso": "2023-06-12T01:35:30+00:00"
}
]
}
$ certbot certificates | jc --certbot -p -r
{
"certificates": [
{
"name": "example.com",
"serial_number": "3f7axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"key_type": "RSA",
"domains": [
"example.com",
"www.example.com"
],
"expiration_date": "2023-05-11 01:33:10+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.com/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.com/priv.pem"
},
{
"name": "example.org",
"serial_number": "3bcyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"key_type": "RSA",
"domains": [
"example.org",
"www.example.org"
],
"expiration_date": "2023-06-12 01:35:30+00:00",
"validity": "63 days",
"certificate_path": "/etc/letsencrypt/live/example.org/chain.pem",
"private_key_path": "/etc/letsencrypt/live/example.org/key.pem"
}
]
}
$ certbot show_account | jc --certbot -p
{
"account": {
"server": "https://acme-staging-v02.api.letsencrypt.org/directory",
"url": "https://acme-staging-v02.api.letsencrypt.org/acme/acct/123",
"email": "some@example.com"
}
}
"""
import re
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.1'
description = '`certbot` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['command']
magic_commands = ['certbot']
__version__ = info.version
def _process(proc_data: JSONDictType) -> JSONDictType:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
Dictionary. Structured to conform to the schema.
"""
if 'certificates' in proc_data:
for cert in proc_data['certificates']:
if 'expiration_date' in cert:
dt = jc.utils.timestamp(cert['expiration_date'], format_hint=(1760,))
cert['expiration_date_epoch'] = dt.naive
cert['expiration_date_epoch_utc'] = dt.utc
cert['expiration_date_iso'] = dt.iso
return proc_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> JSONDictType:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: Dict = {}
cert_list: List = []
cert_dict: Dict = {}
acct_dict: Dict = {}
cmd_option = ''
if jc.utils.has_data(data):
cert_pattern = re.compile(r'^Found the following certs:$', re.MULTILINE)
if re.search(cert_pattern, data):
cmd_option = 'certificates'
else:
cmd_option = 'account'
for line in filter(None, data.splitlines()):
if cmd_option == 'certificates':
if line.startswith(' Certificate Name:'):
if cert_dict:
cert_list.append(cert_dict)
cert_dict = {}
cert_dict['name'] = line.split()[-1]
if line.startswith(' Serial Number:'):
cert_dict['serial_number'] = line.split()[-1]
if line.startswith(' Key Type:'):
cert_dict['key_type'] = line.split(': ', maxsplit=1)[1]
if line.startswith(' Domains:'):
splitline = line.split(': ', maxsplit=1)[1]
cert_dict['domains'] = splitline.split()
if line.startswith(' Expiry Date:'):
splitline = line.split(': ', maxsplit=1)[1]
cert_datetime = splitline.split('(')[0]
validity = splitline.split('(')[1]
cert_dict['expiration_date'] = cert_datetime.strip()
cert_dict['validity'] = validity[:-1].replace('VALID: ', '')
if line.startswith(' Certificate Path:'):
cert_dict['certificate_path'] = line.split(': ', maxsplit=1)[1]
if line.startswith(' Private Key Path:'):
cert_dict['private_key_path'] = line.split(': ', maxsplit=1)[1]
if cmd_option == 'account':
if line.startswith('Account details for server'):
acct_dict['server'] = line.split()[-1][:-1]
if line.startswith(' Account URL:'):
acct_dict['url'] = line.split()[-1]
if line.startswith(' Email contact:'):
acct_dict['email'] = line.split()[-1]
if acct_dict:
raw_output['account'] = acct_dict
if cert_dict:
cert_list.append(cert_dict)
if cert_list:
raw_output['certificates'] = cert_list
return raw_output if raw else _process(raw_output)

View File

@@ -63,6 +63,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['chage --list', 'chage -l']
tags = ['command']
__version__ = info.version

View File

@@ -60,6 +60,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
magic_commands = ['cksum', 'sum']
tags = ['command']
__version__ = info.version

299
jc/parsers/clf.py Normal file
View File

@@ -0,0 +1,299 @@
"""jc - JSON Convert Common Log Format file parser
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf
Usage (module):
import jc
result = jc.parse('clf', common_log_file_output)
Schema:
Empty strings and `-` values are converted to `null`/`None`.
[
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
]
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf -p
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": 10,
"month": "Oct",
"year": 2000,
"hour": 13,
"minute": 55,
"second": 36,
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": 200,
"bytes": 2326,
"referer": null,
"user_agent": null,
"extra": null,
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0",
"epoch": 971211336,
"epoch_utc": null
},
{
"host": "1.1.1.2",
"ident": null,
"authuser": null,
"date": "11/Nov/2016:03:04:55 +0100",
"day": 11,
"month": "Nov",
"year": 2016,
"hour": 3,
"minute": 4,
"second": 55,
"tz": "+0100",
"request": "GET /",
"status": 200,
"bytes": 83,
"referer": null,
"user_agent": null,
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null,
"epoch": 1478862295,
"epoch_utc": null
},
...
]
$ cat file.log | jc --clf -p -r
[
{
"host": "127.0.0.1",
"ident": "user-identifier",
"authuser": "frank",
"date": "10/Oct/2000:13:55:36 -0700",
"day": "10",
"month": "Oct",
"year": "2000",
"hour": "13",
"minute": "55",
"second": "36",
"tz": "-0700",
"request": "GET /apache_pb.gif HTTPS/1.0",
"status": "200",
"bytes": "2326",
"referer": null,
"user_agent": null,
"extra": "",
"request_method": "GET",
"request_url": "/apache_pb.gif",
"request_version": "HTTPS/1.0"
},
{
"host": "1.1.1.2",
"ident": "-",
"authuser": "-",
"date": "11/Nov/2016:03:04:55 +0100",
"day": "11",
"month": "Nov",
"year": "2016",
"hour": "03",
"minute": "04",
"second": "55",
"tz": "+0100",
"request": "GET /",
"status": "200",
"bytes": "83",
"referer": "-",
"user_agent": "-",
"extra": "- 9221 1.1.1.1",
"request_method": "GET",
"request_url": "/",
"request_version": null
},
...
]
"""
import re
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'Common and Combined Log Format file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
__version__ = info.version
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
int_list = {'day', 'year', 'hour', 'minute', 'second', 'status', 'bytes'}
for log in proc_data:
for key, val in log.items():
# integer conversions
if key in int_list:
log[key] = jc.utils.convert_to_int(val)
# convert `-` and blank values to None
if val == '-' or val == '':
log[key] = None
# add unix timestamps
if 'date' in log:
ts = jc.utils.timestamp(log['date'], format_hint=(1800,))
log['epoch'] = ts.naive
log['epoch_utc'] = ts.utc
return proc_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[JSONDictType]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List[Dict] = []
output_line: Dict = {}
clf_pattern = re.compile(r'''
^(?P<host>-|\S+)\s
(?P<ident>-|\S+)\s
(?P<authuser>-|\S+)\s
\[
(?P<date>
(?P<day>\d+)/
(?P<month>\S\S\S)/
(?P<year>\d\d\d\d):
(?P<hour>\d\d):
(?P<minute>\d\d):
(?P<second>\d\d)\s
(?P<tz>\S+)
)
\]\s
\"(?P<request>.*?)\"\s
(?P<status>-|\d\d\d)\s
(?P<bytes>-|\d+)\s?
(?:\"(?P<referer>.*?)\"\s?)?
(?:\"(?P<user_agent>.*?)\"\s?)?
(?P<extra>.*)
''', re.VERBOSE
)
request_pattern = re.compile(r'''
(?P<request_method>\S+)\s
(?P<request_url>.*?(?=\sHTTPS?/|$))\s? # positive lookahead for HTTP(S)/ or end of string
(?P<request_version>HTTPS?/[\d\.]+)?
''', re.VERBOSE
)
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
output_line = {}
clf_match = re.match(clf_pattern, line)
if clf_match:
output_line = clf_match.groupdict()
if output_line.get('request', None):
request_string = output_line['request']
request_match = re.match(request_pattern, request_string)
if request_match:
output_line.update(request_match.groupdict())
raw_output.append(output_line)
else:
raw_output.append(
{"unparsable": line}
)
return raw_output if raw else _process(raw_output)

224
jc/parsers/clf_s.py Normal file
View File

@@ -0,0 +1,224 @@
"""jc - JSON Convert Common Log Format file streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
This parser will handle the Common Log Format standard as specified at
https://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format.
Combined Log Format is also supported. (Referer and User Agent fields added)
Extra fields may be present and will be enclosed in the `extra` field as
a single string.
If a log line cannot be parsed, an object with an `unparsable` field will
be present with a value of the original line.
The `epoch` calculated timestamp field is naive. (i.e. based on the
local time of the system the parser is run on)
The `epoch_utc` calculated timestamp field is timezone-aware and is
only available if the timezone field is UTC.
Usage (cli):
$ cat file.log | jc --clf-s
Usage (module):
import jc
result = jc.parse('clf_s', common_log_file_output.splitlines())
for item in result:
# do something
Schema:
Empty strings and `-` values are converted to `null`/`None`.
{
"host": string,
"ident": string,
"authuser": string,
"date": string,
"day": integer,
"month": string,
"year": integer,
"hour": integer,
"minute": integer,
"second": integer,
"tz": string,
"request": string,
"request_method": string,
"request_url": string,
"request_version": string,
"status": integer,
"bytes": integer,
"referer": string,
"user_agent": string,
"extra": string,
"epoch": integer, # [0]
"epoch_utc": integer, # [1]
"unparsable": string # [2]
}
[0] naive timestamp
[1] timezone-aware timestamp. Only available if timezone field is UTC
[2] exists if the line was not able to be parsed
Examples:
$ cat file.log | jc --clf-s
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":null,"authuser":null,"date":"11/Nov/2016...}
...
$ cat file.log | jc --clf-s -r
{"host":"127.0.0.1","ident":"user-identifier","authuser":"frank","...}
{"host":"1.1.1.2","ident":"-","authuser":"-","date":"11/Nov/2016:0...}
...
"""
import re
from typing import Dict, Iterable
import jc.utils
from jc.streaming import (
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
)
from jc.jc_types import JSONDictType, StreamingOutputType
from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'Common and Combined Log Format file streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
streaming = True
__version__ = info.version
def _process(proc_data: JSONDictType) -> JSONDictType:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (Dictionary) raw structured data to process
Returns:
Dictionary. Structured data to conform to the schema.
"""
int_list = {'day', 'year', 'hour', 'minute', 'second', 'status', 'bytes'}
for key, val in proc_data.items():
# integer conversions
if key in int_list:
proc_data[key] = jc.utils.convert_to_int(val)
# convert `-` and blank values to None
if val == '-' or val == '':
proc_data[key] = None
# add unix timestamps
if 'date' in proc_data:
ts = jc.utils.timestamp(proc_data['date'], format_hint=(1800,))
proc_data['epoch'] = ts.naive
proc_data['epoch_utc'] = ts.utc
return proc_data
@add_jc_meta
def parse(
data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False
) -> StreamingOutputType:
"""
Main text parsing generator function. Returns an iterable object.
Parameters:
data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Returns:
Iterable of Dictionaries
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
streaming_input_type_check(data)
clf_pattern = re.compile(r'''
^(?P<host>-|\S+)\s
(?P<ident>-|\S+)\s
(?P<authuser>-|\S+)\s
\[
(?P<date>
(?P<day>\d+)/
(?P<month>\S\S\S)/
(?P<year>\d\d\d\d):
(?P<hour>\d\d):
(?P<minute>\d\d):
(?P<second>\d\d)\s
(?P<tz>\S+)
)
\]\s
\"(?P<request>.*?)\"\s
(?P<status>-|\d\d\d)\s
(?P<bytes>-|\d+)\s?
(?:\"(?P<referer>.*?)\"\s?)?
(?:\"(?P<user_agent>.*?)\"\s?)?
(?P<extra>.*)
''', re.VERBOSE
)
request_pattern = re.compile(r'''
(?P<request_method>\S+)\s
(?P<request_url>.*?(?=\sHTTPS?/|$))\s? # positive lookahead for HTTP(S)/ or end of string
(?P<request_version>HTTPS?/[\d\.]+)?
''', re.VERBOSE
)
for line in data:
try:
streaming_line_input_type_check(line)
output_line: Dict = {}
if not line.strip():
continue
clf_match = re.match(clf_pattern, line)
if clf_match:
output_line = clf_match.groupdict()
if output_line.get('request', None):
request_string = output_line['request']
request_match = re.match(request_pattern, request_string)
if request_match:
output_line.update(request_match.groupdict())
else:
output_line = {"unparsable": line.strip()}
if output_line:
yield output_line if raw else _process(output_line)
else:
raise ParseError('Not Common Log Format data')
except Exception as e:
yield raise_or_yield(ignore_exceptions, e, line)

View File

@@ -174,12 +174,13 @@ import jc.parsers.universal
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.6'
version = '1.8'
description = '`crontab` command and file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'aix', 'freebsd']
magic_commands = ['crontab']
tags = ['file', 'command']
__version__ = info.version
@@ -244,7 +245,11 @@ def parse(data, raw=False, quiet=False):
# Pop any variable assignment lines
cron_var = []
for i, line in reversed(list(enumerate(cleandata))):
if '=' in line and not line.strip()[0].isdigit() and not line.strip()[0] == '@':
if '=' in line \
and not line.strip()[0].isdigit() \
and not line.strip()[0] == '@' \
and not line.strip()[0] == '*':
var_line = cleandata.pop(i)
var_name = var_line.split('=', maxsplit=1)[0].strip()
var_value = var_line.split('=', maxsplit=1)[1].strip()
@@ -272,6 +277,9 @@ def parse(data, raw=False, quiet=False):
raw_output['schedule'] = cron_list
# Add shortcut entries back in
if 'schedule' not in raw_output:
raw_output['schedule'] = []
for item in shortcut_list:
raw_output['schedule'].append(item)

View File

@@ -171,11 +171,12 @@ import jc.parsers.universal
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.7'
version = '1.9'
description = '`crontab` file parser with user support'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'aix', 'freebsd']
tags = ['file', 'command']
__version__ = info.version
@@ -240,7 +241,11 @@ def parse(data, raw=False, quiet=False):
# Pop any variable assignment lines
cron_var = []
for i, line in reversed(list(enumerate(cleandata))):
if '=' in line and not line.strip()[0].isdigit() and not line.strip()[0] == '@':
if '=' in line \
and not line.strip()[0].isdigit() \
and not line.strip()[0] == '@' \
and not line.strip()[0] == '*':
var_line = cleandata.pop(i)
var_name = var_line.split('=', maxsplit=1)[0].strip()
var_value = var_line.split('=', maxsplit=1)[1].strip()
@@ -270,6 +275,9 @@ def parse(data, raw=False, quiet=False):
raw_output['schedule'] = cron_list
# Add shortcut entries back in
if 'schedule' not in raw_output:
raw_output['schedule'] = []
for item in shortcut_list:
raw_output['schedule'].append(item)

View File

@@ -86,6 +86,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the python standard csv library'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
__version__ = info.version

View File

@@ -69,6 +69,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the python standard csv library'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string']
streaming = True

View File

@@ -84,6 +84,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'freebsd']
magic_commands = ['date']
tags = ['command']
__version__ = info.version

View File

@@ -1,7 +1,7 @@
"""jc - JSON Convert ISO 8601 Datetime string parser
This parser supports standard ISO 8601 strings that include both date and
time. If no timezone or offset information is available in the sring, then
time. If no timezone or offset information is available in the string, then
UTC timezone is used.
Usage (cli):
@@ -75,6 +75,7 @@ class info():
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the pyiso8601 library from https://github.com/micktwomey/pyiso8601/releases/tag/1.0.2'
compatible = ['linux', 'aix', 'freebsd', 'darwin', 'win32', 'cygwin']
tags = ['standard', 'string']
__version__ = info.version

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