mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-03 04:52:24 +00:00
sphinx experiments
This commit is contained in:
parent
79b1128a5a
commit
e29a459fb5
19 changed files with 2870 additions and 0 deletions
2
docs/.vimrc
Normal file
2
docs/.vimrc
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
map \f :w<C-m>:!clear;make html<C-m>
|
||||
map \d :w<C-m>:!clear;make clean html<C-m>
|
||||
2
docs/10-1.sh
Executable file
2
docs/10-1.sh
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
grep op=cache log.txt \
|
||||
| mlr --idkvp --opprint stats1 -a mean -f hit -g type then sort -f type
|
||||
5
docs/10-2.sh
Executable file
5
docs/10-2.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
mlr --from log.txt --opprint \
|
||||
filter 'is_present($batch_size)' \
|
||||
then step -a delta -f time,num_filtered \
|
||||
then sec2gmt time
|
||||
|
||||
794
docs/10min.rst
Normal file
794
docs/10min.rst
Normal file
|
|
@ -0,0 +1,794 @@
|
|||
Miller in 10 minutes
|
||||
====================
|
||||
|
||||
CSV-file examples
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Suppose you have this CSV data file::
|
||||
|
||||
$ cat example.csv
|
||||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
red,square,0,48,77.5542,7.4670
|
||||
purple,triangle,0,51,81.2290,8.5910
|
||||
red,square,0,64,77.1991,9.5310
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
||||
``mlr cat`` is like cat -- it passes the data through unmodified::
|
||||
|
||||
$ mlr --csv cat example.csv
|
||||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
red,square,0,48,77.5542,7.4670
|
||||
purple,triangle,0,51,81.2290,8.5910
|
||||
red,square,0,64,77.1991,9.5310
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
||||
but it can also do format conversion (here, you can pretty-print in tabular format)::
|
||||
|
||||
$ mlr --icsv --opprint cat example.csv
|
||||
color shape flag index quantity rate
|
||||
yellow triangle 1 11 43.6498 9.8870
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
red square 0 48 77.5542 7.4670
|
||||
purple triangle 0 51 81.2290 8.5910
|
||||
red square 0 64 77.1991 9.5310
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
purple square 0 91 72.3735 8.2430
|
||||
|
||||
``mlr head`` and ``mlr tail`` count records rather than lines. Whethere you're getting the first few records or the last few, the CSV header is included either way::
|
||||
|
||||
$ mlr --csv head -n 4 example.csv
|
||||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
red,square,0,48,77.5542,7.4670
|
||||
$ mlr --csv tail -n 4 example.csv
|
||||
color,shape,flag,index,quantity,rate
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
||||
You can sort primarily alphabetically on one field, then secondarily numerically descending on another field::
|
||||
|
||||
$ mlr --icsv --opprint sort -f shape -nr index example.csv
|
||||
color shape flag index quantity rate
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
red circle 1 16 13.8103 2.9010
|
||||
purple square 0 91 72.3735 8.2430
|
||||
red square 0 64 77.1991 9.5310
|
||||
red square 0 48 77.5542 7.4670
|
||||
red square 1 15 79.2778 0.0130
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
purple triangle 0 51 81.2290 8.5910
|
||||
yellow triangle 1 11 43.6498 9.8870
|
||||
|
||||
You can use ``cut`` to retain only specified fields, in the same order they appeared in the input data::
|
||||
|
||||
$ mlr --icsv --opprint cut -f flag,shape example.csv
|
||||
shape flag
|
||||
triangle 1
|
||||
square 1
|
||||
circle 1
|
||||
square 0
|
||||
triangle 0
|
||||
square 0
|
||||
triangle 0
|
||||
circle 1
|
||||
circle 1
|
||||
square 0
|
||||
|
||||
You can also use ``cut -o`` to retain only specified fields in your preferred order::
|
||||
|
||||
$ mlr --icsv --opprint cut -o -f flag,shape example.csv
|
||||
flag shape
|
||||
1 triangle
|
||||
1 square
|
||||
1 circle
|
||||
0 square
|
||||
0 triangle
|
||||
0 square
|
||||
0 triangle
|
||||
1 circle
|
||||
1 circle
|
||||
0 square
|
||||
|
||||
You can use ``cut -x`` to omit fields you don't care about::
|
||||
|
||||
$ mlr --icsv --opprint cut -x -f flag,shape example.csv
|
||||
color index quantity rate
|
||||
yellow 11 43.6498 9.8870
|
||||
red 15 79.2778 0.0130
|
||||
red 16 13.8103 2.9010
|
||||
red 48 77.5542 7.4670
|
||||
purple 51 81.2290 8.5910
|
||||
red 64 77.1991 9.5310
|
||||
purple 65 80.1405 5.8240
|
||||
yellow 73 63.9785 4.2370
|
||||
yellow 87 63.5058 8.3350
|
||||
purple 91 72.3735 8.2430
|
||||
|
||||
You can use ``filter`` to keep only records you care about::
|
||||
|
||||
$ mlr --icsv --opprint filter '$color == "red"' example.csv
|
||||
color shape flag index quantity rate
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
red square 0 48 77.5542 7.4670
|
||||
red square 0 64 77.1991 9.5310
|
||||
$ mlr --icsv --opprint filter '$color == "red" && $flag == 1' example.csv
|
||||
color shape flag index quantity rate
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
|
||||
You can use ``put`` to create new fields which are computed from other fields::
|
||||
|
||||
$ mlr --icsv --opprint put '$ratio = $quantity / $rate; $color_shape = $color . "_" . $shape' example.csv
|
||||
color shape flag index quantity rate ratio color_shape
|
||||
yellow triangle 1 11 43.6498 9.8870 4.414868 yellow_triangle
|
||||
red square 1 15 79.2778 0.0130 6098.292308 red_square
|
||||
red circle 1 16 13.8103 2.9010 4.760531 red_circle
|
||||
red square 0 48 77.5542 7.4670 10.386260 red_square
|
||||
purple triangle 0 51 81.2290 8.5910 9.455127 purple_triangle
|
||||
red square 0 64 77.1991 9.5310 8.099790 red_square
|
||||
purple triangle 0 65 80.1405 5.8240 13.760388 purple_triangle
|
||||
yellow circle 1 73 63.9785 4.2370 15.099953 yellow_circle
|
||||
yellow circle 1 87 63.5058 8.3350 7.619172 yellow_circle
|
||||
purple square 0 91 72.3735 8.2430 8.779995 purple_square
|
||||
|
||||
Even though Miller's main selling point is name-indexing, sometimes you really want to refer to a field name by its positional index. Use ``$[[3]]`` to access the name of field 3 or ``$[[[3]]]`` to access the value of field 3::
|
||||
|
||||
$ mlr --icsv --opprint put '$[[3]] = "NEW"' example.csv
|
||||
color shape NEW index quantity rate
|
||||
yellow triangle 1 11 43.6498 9.8870
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
red square 0 48 77.5542 7.4670
|
||||
purple triangle 0 51 81.2290 8.5910
|
||||
red square 0 64 77.1991 9.5310
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
purple square 0 91 72.3735 8.2430
|
||||
$ mlr --icsv --opprint put '$[[[3]]] = "NEW"' example.csv
|
||||
color shape flag index quantity rate
|
||||
yellow triangle NEW 11 43.6498 9.8870
|
||||
red square NEW 15 79.2778 0.0130
|
||||
red circle NEW 16 13.8103 2.9010
|
||||
red square NEW 48 77.5542 7.4670
|
||||
purple triangle NEW 51 81.2290 8.5910
|
||||
red square NEW 64 77.1991 9.5310
|
||||
purple triangle NEW 65 80.1405 5.8240
|
||||
yellow circle NEW 73 63.9785 4.2370
|
||||
yellow circle NEW 87 63.5058 8.3350
|
||||
purple square NEW 91 72.3735 8.2430
|
||||
|
||||
JSON-file examples
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
OK, CSV and pretty-print are fine. But Miller can also convert between a few other formats -- let's take a look at JSON output::
|
||||
|
||||
$ mlr --icsv --ojson put '$ratio = $quantity/$rate; $shape = toupper($shape)' example.csv
|
||||
{ "color": "yellow", "shape": "TRIANGLE", "flag": 1, "index": 11, "quantity": 43.6498, "rate": 9.8870, "ratio": 4.414868 }
|
||||
{ "color": "red", "shape": "SQUARE", "flag": 1, "index": 15, "quantity": 79.2778, "rate": 0.0130, "ratio": 6098.292308 }
|
||||
{ "color": "red", "shape": "CIRCLE", "flag": 1, "index": 16, "quantity": 13.8103, "rate": 2.9010, "ratio": 4.760531 }
|
||||
{ "color": "red", "shape": "SQUARE", "flag": 0, "index": 48, "quantity": 77.5542, "rate": 7.4670, "ratio": 10.386260 }
|
||||
{ "color": "purple", "shape": "TRIANGLE", "flag": 0, "index": 51, "quantity": 81.2290, "rate": 8.5910, "ratio": 9.455127 }
|
||||
{ "color": "red", "shape": "SQUARE", "flag": 0, "index": 64, "quantity": 77.1991, "rate": 9.5310, "ratio": 8.099790 }
|
||||
{ "color": "purple", "shape": "TRIANGLE", "flag": 0, "index": 65, "quantity": 80.1405, "rate": 5.8240, "ratio": 13.760388 }
|
||||
{ "color": "yellow", "shape": "CIRCLE", "flag": 1, "index": 73, "quantity": 63.9785, "rate": 4.2370, "ratio": 15.099953 }
|
||||
{ "color": "yellow", "shape": "CIRCLE", "flag": 1, "index": 87, "quantity": 63.5058, "rate": 8.3350, "ratio": 7.619172 }
|
||||
{ "color": "purple", "shape": "SQUARE", "flag": 0, "index": 91, "quantity": 72.3735, "rate": 8.2430, "ratio": 8.779995 }
|
||||
|
||||
Or, JSON output with vertical-formatting flags::
|
||||
|
||||
$ mlr --icsv --ojsonx tail -n 2 example.csv
|
||||
{
|
||||
"color": "yellow",
|
||||
"shape": "circle",
|
||||
"flag": 1,
|
||||
"index": 87,
|
||||
"quantity": 63.5058,
|
||||
"rate": 8.3350
|
||||
}
|
||||
{
|
||||
"color": "purple",
|
||||
"shape": "square",
|
||||
"flag": 0,
|
||||
"index": 91,
|
||||
"quantity": 72.3735,
|
||||
"rate": 8.2430
|
||||
}
|
||||
|
||||
Sorts and stats
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Now suppose you want to sort the data on a given column, *and then* take the top few in that ordering. You can use Miller's ``then`` feature to pipe commands together.
|
||||
|
||||
Here are the records with the top three ``index`` values::
|
||||
|
||||
$ mlr --icsv --opprint sort -f shape -nr index then head -n 3 example.csv
|
||||
color shape flag index quantity rate
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
red circle 1 16 13.8103 2.9010
|
||||
|
||||
Lots of Miller commands take a ``-g`` option for group-by: here, ``head -n 1 -g shape`` outputs the first record for each distinct value of the ``shape`` field. This means we're finding the record with highest ``index`` field for each distinct ``shape`` field::
|
||||
|
||||
$ mlr --icsv --opprint sort -f shape -nr index then head -n 1 -g shape example.csv
|
||||
color shape flag index quantity rate
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
purple square 0 91 72.3735 8.2430
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
|
||||
Statistics can be computed with or without group-by field(s)::
|
||||
|
||||
$ mlr --icsv --opprint --from example.csv stats1 -a count,min,mean,max -f quantity -g shape
|
||||
shape quantity_count quantity_min quantity_mean quantity_max
|
||||
triangle 3 43.649800 68.339767 81.229000
|
||||
square 4 72.373500 76.601150 79.277800
|
||||
circle 3 13.810300 47.098200 63.978500
|
||||
$ mlr --icsv --opprint --from example.csv stats1 -a count,min,mean,max -f quantity -g shape,color
|
||||
shape color quantity_count quantity_min quantity_mean quantity_max
|
||||
triangle yellow 1 43.649800 43.649800 43.649800
|
||||
square red 3 77.199100 78.010367 79.277800
|
||||
circle red 1 13.810300 13.810300 13.810300
|
||||
triangle purple 2 80.140500 80.684750 81.229000
|
||||
circle yellow 2 63.505800 63.742150 63.978500
|
||||
square purple 1 72.373500 72.373500 72.373500
|
||||
|
||||
If your output has a lot of columns, you can use XTAB format to line things up vertically for you instead::
|
||||
|
||||
$ mlr --icsv --oxtab --from example.csv stats1 -a p0,p10,p25,p50,p75,p90,p99,p100 -f rate
|
||||
rate_p0 0.013000
|
||||
rate_p10 2.901000
|
||||
rate_p25 4.237000
|
||||
rate_p50 8.243000
|
||||
rate_p75 8.591000
|
||||
rate_p90 9.887000
|
||||
rate_p99 9.887000
|
||||
rate_p100 9.887000
|
||||
|
||||
Choices for printing to files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Often we want to print output <span class="boldmaroon">to the screen</span>. Miller does this by default, as we've seen in the previous examples.
|
||||
|
||||
Sometimes we want to print output to another file: <span class="boldmaroon">just use '> outputfilenamegoeshere'</span> at the end of your command::
|
||||
|
||||
% mlr --icsv --opprint cat example.csv > newfile.csv
|
||||
# Output goes to the new file;
|
||||
# nothing is printed to the screen.
|
||||
</pre> </div>
|
||||
</td><td>
|
||||
<div class="pokipanel"> <pre>
|
||||
% cat newfile.csv
|
||||
color shape flag index quantity rate
|
||||
yellow triangle 1 11 43.6498 9.8870
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
red square 0 48 77.5542 7.4670
|
||||
purple triangle 0 51 81.2290 8.5910
|
||||
red square 0 64 77.1991 9.5310
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
purple square 0 91 72.3735 8.2430
|
||||
|
||||
Other times we just want our files to be changed in-place: <span class="boldmaroon">just use 'mlr -I'</span>.::
|
||||
|
||||
% cp example.csv newfile.txt
|
||||
|
||||
% cat newfile.txt
|
||||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
red,square,0,48,77.5542,7.4670
|
||||
purple,triangle,0,51,81.2290,8.5910
|
||||
red,square,0,64,77.1991,9.5310
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
||||
% mlr -I --icsv --opprint cat newfile.txt
|
||||
|
||||
% cat newfile.txt
|
||||
color shape flag index quantity rate
|
||||
yellow triangle 1 11 43.6498 9.8870
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
red square 0 48 77.5542 7.4670
|
||||
purple triangle 0 51 81.2290 8.5910
|
||||
red square 0 64 77.1991 9.5310
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
purple square 0 91 72.3735 8.2430
|
||||
|
||||
Also using ``mlr -I`` you can bulk-operate on lots of files: e.g.::
|
||||
|
||||
mlr -I --csv cut -x -f unwanted_column_name *.csv
|
||||
|
||||
If you like, you can first copy off your original data somewhere else, before doing in-place operations.
|
||||
|
||||
Lastly, using ``tee`` within ``put``, you can split your input data into separate files per one or more field names::
|
||||
|
||||
$ mlr --csv --from example.csv put -q 'tee > $shape.".csv", $*'
|
||||
|
||||
$ cat circle.csv
|
||||
color,shape,flag,index,quantity,rate
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
|
||||
$ cat square.csv
|
||||
color,shape,flag,index,quantity,rate
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,square,0,48,77.5542,7.4670
|
||||
red,square,0,64,77.1991,9.5310
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
||||
$ cat triangle.csv
|
||||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
purple,triangle,0,51,81.2290,8.5910
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
|
||||
|
||||
Other-format examples
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
What's a CSV file, really? It's an array of rows, or *records*, each being a list of key-value pairs, or *fields*: for CSV it so happens that all the keys are shared in the header line and the values vary data line by data line.
|
||||
|
||||
For example, if you have::
|
||||
|
||||
shape,flag,index
|
||||
circle,1,24
|
||||
square,0,36
|
||||
</pre>
|
||||
|
||||
then that's a way of saying::
|
||||
|
||||
shape=circle,flag=1,index=24
|
||||
shape=square,flag=0,index=36
|
||||
|
||||
Data written this way are called <span class="boldmaroon">DKVP</span>, for *delimited key-value pairs*.
|
||||
|
||||
We've also already seen other ways to write the same data::
|
||||
|
||||
CSV PPRINT JSON
|
||||
shape,flag,index shape flag index [
|
||||
circle,1,24 circle 1 24 {
|
||||
square,0,36 square 0 36 "shape": "circle",
|
||||
"flag": 1,
|
||||
"index": 24
|
||||
},
|
||||
DKVP XTAB {
|
||||
shape=circle,flag=1,index=24 shape circle "shape": "square",
|
||||
shape=square,flag=0,index=36 flag 1 "flag": 0,
|
||||
index 24 "index": 36
|
||||
}
|
||||
shape square ]
|
||||
flag 0
|
||||
index 36
|
||||
|
||||
Anything we can do with CSV input data, we can do with any other format input data. And you can read from one format, do any record-processing, and output to the same format as the input, or to a different output format.
|
||||
|
||||
SQL-output examples
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
I like to produce SQL-query output with header-column and tab delimiter: this is CSV but with a tab instead of a comma, also known as TSV. Then I post-process with ``mlr --tsv`` or ``mlr --tsvlite``. This means I can do some (or all, or none) of my data processing within SQL queries, and some (or none, or all) of my data processing using Miller -- whichever is most convenient for my needs at the moment.
|
||||
|
||||
For example, using default output formatting in ``mysql`` we get formatting like Miller's ``--opprint --barred``::
|
||||
|
||||
$ mysql --database=mydb -e 'show columns in mytable'
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| Field | Type | Null | Key | Default | Extra |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| id | bigint(20) | NO | MUL | NULL | |
|
||||
| category | varchar(256) | NO | | NULL | |
|
||||
| is_permanent | tinyint(1) | NO | | NULL | |
|
||||
| assigned_to | bigint(20) | YES | | NULL | |
|
||||
| last_update_time | int(11) | YES | | NULL | |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
|
||||
Using ``mysql``'s ``-B`` we get TSV output::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --opprint cat
|
||||
Field Type Null Key Default Extra
|
||||
id bigint(20) NO MUL NULL -
|
||||
category varchar(256) NO - NULL -
|
||||
is_permanent tinyint(1) NO - NULL -
|
||||
assigned_to bigint(20) YES - NULL -
|
||||
last_update_time int(11) YES - NULL -
|
||||
|
||||
Since Miller handles TSV output, we can do as much or as little processing as we want in the SQL query, then send the rest on to Miller. This includes outputting as JSON, doing further selects/joins in Miller, doing stats, etc. etc.::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson --jlistwrap --jvstack cat
|
||||
[
|
||||
{
|
||||
"Field": "id",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "NO",
|
||||
"Key": "MUL",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "category",
|
||||
"Type": "varchar(256)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "is_permanent",
|
||||
"Type": "tinyint(1)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "assigned_to",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "last_update_time",
|
||||
"Type": "int(11)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
}
|
||||
]
|
||||
|
||||
$ mysql --database=mydb -B -e 'select * from mytable' > query.tsv
|
||||
|
||||
$ mlr --from query.tsv --t2p stats1 -a count -f id -g category,assigned_to
|
||||
category assigned_to id_count
|
||||
special 10000978 207
|
||||
special 10003924 385
|
||||
special 10009872 168
|
||||
standard 10000978 524
|
||||
standard 10003924 392
|
||||
standard 10009872 108
|
||||
...
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags.
|
||||
|
||||
SQL-input examples
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One use of NIDX (value-only, no keys) format is for loading up SQL tables.
|
||||
|
||||
Create and load SQL table::
|
||||
|
||||
mysql> CREATE TABLE abixy(
|
||||
a VARCHAR(32),
|
||||
b VARCHAR(32),
|
||||
i BIGINT(10),
|
||||
x DOUBLE,
|
||||
y DOUBLE
|
||||
);
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
bash$ mlr --onidx --fs comma cat data/medium > medium.nidx
|
||||
|
||||
mysql> LOAD DATA LOCAL INFILE 'medium.nidx' REPLACE INTO TABLE abixy FIELDS TERMINATED BY ',' ;
|
||||
Query OK, 10000 rows affected (0.07 sec)
|
||||
Records: 10000 Deleted: 0 Skipped: 0 Warnings: 0
|
||||
|
||||
mysql> SELECT COUNT(*) AS count FROM abixy;
|
||||
+-------+
|
||||
| count |
|
||||
+-------+
|
||||
| 10000 |
|
||||
+-------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mysql> SELECT * FROM abixy LIMIT 10;
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| a | b | i | x | y |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| pan | pan | 1 | 0.3467901443380824 | 0.7268028627434533 |
|
||||
| eks | pan | 2 | 0.7586799647899636 | 0.5221511083334797 |
|
||||
| wye | wye | 3 | 0.20460330576630303 | 0.33831852551664776 |
|
||||
| eks | wye | 4 | 0.38139939387114097 | 0.13418874328430463 |
|
||||
| wye | pan | 5 | 0.5732889198020006 | 0.8636244699032729 |
|
||||
| zee | pan | 6 | 0.5271261600918548 | 0.49322128674835697 |
|
||||
| eks | zee | 7 | 0.6117840605678454 | 0.1878849191181694 |
|
||||
| zee | wye | 8 | 0.5985540091064224 | 0.976181385699006 |
|
||||
| hat | wye | 9 | 0.03144187646093577 | 0.7495507603507059 |
|
||||
| pan | wye | 10 | 0.5026260055412137 | 0.9526183602969864 |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
|
||||
Aggregate counts within SQL::
|
||||
|
||||
mysql> SELECT a, b, COUNT(*) AS count FROM abixy GROUP BY a, b ORDER BY COUNT DESC;
|
||||
+------+------+-------+
|
||||
| a | b | count |
|
||||
+------+------+-------+
|
||||
| zee | wye | 455 |
|
||||
| pan | eks | 429 |
|
||||
| pan | pan | 427 |
|
||||
| wye | hat | 426 |
|
||||
| hat | wye | 423 |
|
||||
| pan | hat | 417 |
|
||||
| eks | hat | 417 |
|
||||
| pan | zee | 413 |
|
||||
| eks | eks | 413 |
|
||||
| zee | hat | 409 |
|
||||
| eks | wye | 407 |
|
||||
| zee | zee | 403 |
|
||||
| pan | wye | 395 |
|
||||
| wye | pan | 392 |
|
||||
| zee | eks | 391 |
|
||||
| zee | pan | 389 |
|
||||
| hat | eks | 389 |
|
||||
| wye | eks | 386 |
|
||||
| wye | zee | 385 |
|
||||
| hat | zee | 385 |
|
||||
| hat | hat | 381 |
|
||||
| wye | wye | 377 |
|
||||
| eks | pan | 371 |
|
||||
| hat | pan | 363 |
|
||||
| eks | zee | 357 |
|
||||
+------+------+-------+
|
||||
25 rows in set (0.01 sec)
|
||||
|
||||
Aggregate counts within Miller::
|
||||
|
||||
$ mlr --opprint uniq -c -g a,b then sort -nr count data/medium
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
|
||||
Pipe SQL output to aggregate counts within Miller::
|
||||
|
||||
$ mysql -D miller -B -e 'select * from abixy' | mlr --itsv --opprint uniq -c -g a,b then sort -nr count
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
wye pan 392
|
||||
zee eks 391
|
||||
zee pan 389
|
||||
hat eks 389
|
||||
wye eks 386
|
||||
hat zee 385
|
||||
wye zee 385
|
||||
hat hat 381
|
||||
wye wye 377
|
||||
eks pan 371
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
|
||||
Log-processing examples
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Another of my favorite use-cases for Miller is doing ad-hoc processing of log-file data. Here's where DKVP format really shines: one, since the field names and field values are present on every line, every line stands on its own. That means you can ``grep`` or what have you. Also it means not every line needs to have the same list of field names ("schema").
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags. But there's more you can do when not all the records have the same shape.
|
||||
|
||||
Writing a program -- in any language whatsoever -- you can have it print out log lines as it goes along, with items for various events jumbled together. After the program has finished running you can sort it all out, filter it, analyze it, and learn from it.
|
||||
|
||||
Suppose your program has printed something like this::
|
||||
|
||||
$ cat log.txt
|
||||
op=enter,time=1472819681
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
time=1472819690,batch_size=100,num_filtered=237
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A1,hit=1
|
||||
time=1472819705,batch_size=100,num_filtered=348
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
time=1472819713,batch_size=100,num_filtered=493
|
||||
op=cache,type=A9,hit=1
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=1
|
||||
time=1472819720,batch_size=100,num_filtered=554
|
||||
op=cache,type=A1,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=0
|
||||
op=cache,type=A4,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
time=1472819736,batch_size=100,num_filtered=612
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
time=1472819742,batch_size=100,num_filtered=728
|
||||
|
||||
Each print statement simply contains local information: the current timestamp, whether a particular cache was hit or not, etc. Then using either the system ``grep`` command, or Miller's ``having-fields``, or ``is_present``, we can pick out the parts we want and analyze them::
|
||||
|
||||
$ grep op=cache log.txt \
|
||||
| mlr --idkvp --opprint stats1 -a mean -f hit -g type then sort -f type
|
||||
type hit_mean
|
||||
A1 0.857143
|
||||
A4 0.714286
|
||||
A9 0.090909
|
||||
$ mlr --from log.txt --opprint \
|
||||
filter 'is_present($batch_size)' \
|
||||
then step -a delta -f time,num_filtered \
|
||||
then sec2gmt time
|
||||
|
||||
time batch_size num_filtered time_delta num_filtered_delta
|
||||
2016-09-02T12:34:50Z 100 237 0 0
|
||||
2016-09-02T12:35:05Z 100 348 15 111
|
||||
2016-09-02T12:35:13Z 100 493 8 145
|
||||
2016-09-02T12:35:20Z 100 554 7 61
|
||||
2016-09-02T12:35:36Z 100 612 16 58
|
||||
2016-09-02T12:35:42Z 100 728 6 116
|
||||
|
||||
Alternatively, we can simply group the similar data for a better look::
|
||||
|
||||
$ mlr --opprint group-like log.txt
|
||||
op time
|
||||
enter 1472819681
|
||||
|
||||
op type hit
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A9 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 1
|
||||
cache A1 0
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 0
|
||||
cache A4 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
|
||||
time batch_size num_filtered
|
||||
1472819690 100 237
|
||||
1472819705 100 348
|
||||
1472819713 100 493
|
||||
1472819720 100 554
|
||||
1472819736 100 612
|
||||
1472819742 100 728
|
||||
$ mlr --opprint group-like then sec2gmt time log.txt
|
||||
op time
|
||||
enter 2016-09-02T12:34:41Z
|
||||
|
||||
op type hit
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A9 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 1
|
||||
cache A1 0
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 0
|
||||
cache A4 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
|
||||
time batch_size num_filtered
|
||||
2016-09-02T12:34:50Z 100 237
|
||||
2016-09-02T12:35:05Z 100 348
|
||||
2016-09-02T12:35:13Z 100 493
|
||||
2016-09-02T12:35:20Z 100 554
|
||||
2016-09-02T12:35:36Z 100 612
|
||||
2016-09-02T12:35:42Z 100 728
|
||||
|
||||
More
|
||||
^^^^
|
||||
|
||||
Please see the <a href="reference.html">reference</a> for complete information, as well as the <a href="faq.html">FAQ</a> and the <a href="cookbook.html">cookbook</a> for more tips.
|
||||
445
docs/10min.rst.in
Normal file
445
docs/10min.rst.in
Normal file
|
|
@ -0,0 +1,445 @@
|
|||
Miller in 10 minutes
|
||||
====================
|
||||
|
||||
CSV-file examples
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Suppose you have this CSV data file::
|
||||
|
||||
POKI_RUN_COMMAND{{cat example.csv}}HERE
|
||||
|
||||
``mlr cat`` is like cat -- it passes the data through unmodified::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --csv cat example.csv}}HERE
|
||||
|
||||
but it can also do format conversion (here, you can pretty-print in tabular format)::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint cat example.csv}}HERE
|
||||
|
||||
``mlr head`` and ``mlr tail`` count records rather than lines. Whethere you're getting the first few records or the last few, the CSV header is included either way::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --csv head -n 4 example.csv}}HERE
|
||||
POKI_RUN_COMMAND{{mlr --csv tail -n 4 example.csv}}HERE
|
||||
|
||||
You can sort primarily alphabetically on one field, then secondarily numerically descending on another field::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint sort -f shape -nr index example.csv}}HERE
|
||||
|
||||
You can use ``cut`` to retain only specified fields, in the same order they appeared in the input data::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint cut -f flag,shape example.csv}}HERE
|
||||
|
||||
You can also use ``cut -o`` to retain only specified fields in your preferred order::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint cut -o -f flag,shape example.csv}}HERE
|
||||
|
||||
You can use ``cut -x`` to omit fields you don't care about::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint cut -x -f flag,shape example.csv}}HERE
|
||||
|
||||
You can use ``filter`` to keep only records you care about::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint filter '$color == "red"' example.csv}}HERE
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint filter '$color == "red" && $flag == 1' example.csv}}HERE
|
||||
|
||||
You can use ``put`` to create new fields which are computed from other fields::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint put '$ratio = $quantity / $rate; $color_shape = $color . "_" . $shape' example.csv}}HERE
|
||||
|
||||
Even though Miller's main selling point is name-indexing, sometimes you really want to refer to a field name by its positional index. Use ``$[[3]]`` to access the name of field 3 or ``$[[[3]]]`` to access the value of field 3::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint put '$[[3]] = "NEW"' example.csv}}HERE
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint put '$[[[3]]] = "NEW"' example.csv}}HERE
|
||||
|
||||
JSON-file examples
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
OK, CSV and pretty-print are fine. But Miller can also convert between a few other formats -- let's take a look at JSON output::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --ojson put '$ratio = $quantity/$rate; $shape = toupper($shape)' example.csv}}HERE
|
||||
|
||||
Or, JSON output with vertical-formatting flags::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --ojsonx tail -n 2 example.csv}}HERE
|
||||
|
||||
Sorts and stats
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Now suppose you want to sort the data on a given column, *and then* take the top few in that ordering. You can use Miller's ``then`` feature to pipe commands together.
|
||||
|
||||
Here are the records with the top three ``index`` values::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint sort -f shape -nr index then head -n 3 example.csv}}HERE
|
||||
|
||||
Lots of Miller commands take a ``-g`` option for group-by: here, ``head -n 1 -g shape`` outputs the first record for each distinct value of the ``shape`` field. This means we're finding the record with highest ``index`` field for each distinct ``shape`` field::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint sort -f shape -nr index then head -n 1 -g shape example.csv}}HERE
|
||||
|
||||
Statistics can be computed with or without group-by field(s)::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint --from example.csv stats1 -a count,min,mean,max -f quantity -g shape}}HERE
|
||||
POKI_RUN_COMMAND{{mlr --icsv --opprint --from example.csv stats1 -a count,min,mean,max -f quantity -g shape,color}}HERE
|
||||
|
||||
If your output has a lot of columns, you can use XTAB format to line things up vertically for you instead::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --icsv --oxtab --from example.csv stats1 -a p0,p10,p25,p50,p75,p90,p99,p100 -f rate}}HERE
|
||||
|
||||
Choices for printing to files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Often we want to print output <span class="boldmaroon">to the screen</span>. Miller does this by default, as we've seen in the previous examples.
|
||||
|
||||
Sometimes we want to print output to another file: <span class="boldmaroon">just use '> outputfilenamegoeshere'</span> at the end of your command::
|
||||
|
||||
% mlr --icsv --opprint cat example.csv > newfile.csv
|
||||
# Output goes to the new file;
|
||||
# nothing is printed to the screen.
|
||||
</pre> </div>
|
||||
</td><td>
|
||||
<div class="pokipanel"> <pre>
|
||||
% cat newfile.csv
|
||||
color shape flag index quantity rate
|
||||
yellow triangle 1 11 43.6498 9.8870
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
red square 0 48 77.5542 7.4670
|
||||
purple triangle 0 51 81.2290 8.5910
|
||||
red square 0 64 77.1991 9.5310
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
purple square 0 91 72.3735 8.2430
|
||||
|
||||
Other times we just want our files to be changed in-place: <span class="boldmaroon">just use 'mlr -I'</span>.::
|
||||
|
||||
% cp example.csv newfile.txt
|
||||
|
||||
% cat newfile.txt
|
||||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
red,square,0,48,77.5542,7.4670
|
||||
purple,triangle,0,51,81.2290,8.5910
|
||||
red,square,0,64,77.1991,9.5310
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
||||
% mlr -I --icsv --opprint cat newfile.txt
|
||||
|
||||
% cat newfile.txt
|
||||
color shape flag index quantity rate
|
||||
yellow triangle 1 11 43.6498 9.8870
|
||||
red square 1 15 79.2778 0.0130
|
||||
red circle 1 16 13.8103 2.9010
|
||||
red square 0 48 77.5542 7.4670
|
||||
purple triangle 0 51 81.2290 8.5910
|
||||
red square 0 64 77.1991 9.5310
|
||||
purple triangle 0 65 80.1405 5.8240
|
||||
yellow circle 1 73 63.9785 4.2370
|
||||
yellow circle 1 87 63.5058 8.3350
|
||||
purple square 0 91 72.3735 8.2430
|
||||
|
||||
Also using ``mlr -I`` you can bulk-operate on lots of files: e.g.::
|
||||
|
||||
mlr -I --csv cut -x -f unwanted_column_name *.csv
|
||||
|
||||
If you like, you can first copy off your original data somewhere else, before doing in-place operations.
|
||||
|
||||
Lastly, using ``tee`` within ``put``, you can split your input data into separate files per one or more field names::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --csv --from example.csv put -q 'tee > $shape.".csv", $*'}}HERE
|
||||
|
||||
POKI_RUN_COMMAND{{cat circle.csv}}HERE
|
||||
|
||||
POKI_RUN_COMMAND{{cat square.csv}}HERE
|
||||
|
||||
POKI_RUN_COMMAND{{cat triangle.csv}}HERE
|
||||
|
||||
|
||||
Other-format examples
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
What's a CSV file, really? It's an array of rows, or *records*, each being a list of key-value pairs, or *fields*: for CSV it so happens that all the keys are shared in the header line and the values vary data line by data line.
|
||||
|
||||
For example, if you have::
|
||||
|
||||
shape,flag,index
|
||||
circle,1,24
|
||||
square,0,36
|
||||
</pre>
|
||||
|
||||
then that's a way of saying::
|
||||
|
||||
shape=circle,flag=1,index=24
|
||||
shape=square,flag=0,index=36
|
||||
|
||||
Data written this way are called <span class="boldmaroon">DKVP</span>, for *delimited key-value pairs*.
|
||||
|
||||
We've also already seen other ways to write the same data::
|
||||
|
||||
CSV PPRINT JSON
|
||||
shape,flag,index shape flag index [
|
||||
circle,1,24 circle 1 24 {
|
||||
square,0,36 square 0 36 "shape": "circle",
|
||||
"flag": 1,
|
||||
"index": 24
|
||||
},
|
||||
DKVP XTAB {
|
||||
shape=circle,flag=1,index=24 shape circle "shape": "square",
|
||||
shape=square,flag=0,index=36 flag 1 "flag": 0,
|
||||
index 24 "index": 36
|
||||
}
|
||||
shape square ]
|
||||
flag 0
|
||||
index 36
|
||||
|
||||
Anything we can do with CSV input data, we can do with any other format input data. And you can read from one format, do any record-processing, and output to the same format as the input, or to a different output format.
|
||||
|
||||
SQL-output examples
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
I like to produce SQL-query output with header-column and tab delimiter: this is CSV but with a tab instead of a comma, also known as TSV. Then I post-process with ``mlr --tsv`` or ``mlr --tsvlite``. This means I can do some (or all, or none) of my data processing within SQL queries, and some (or none, or all) of my data processing using Miller -- whichever is most convenient for my needs at the moment.
|
||||
|
||||
For example, using default output formatting in ``mysql`` we get formatting like Miller's ``--opprint --barred``::
|
||||
|
||||
$ mysql --database=mydb -e 'show columns in mytable'
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| Field | Type | Null | Key | Default | Extra |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| id | bigint(20) | NO | MUL | NULL | |
|
||||
| category | varchar(256) | NO | | NULL | |
|
||||
| is_permanent | tinyint(1) | NO | | NULL | |
|
||||
| assigned_to | bigint(20) | YES | | NULL | |
|
||||
| last_update_time | int(11) | YES | | NULL | |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
|
||||
Using ``mysql``'s ``-B`` we get TSV output::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --opprint cat
|
||||
Field Type Null Key Default Extra
|
||||
id bigint(20) NO MUL NULL -
|
||||
category varchar(256) NO - NULL -
|
||||
is_permanent tinyint(1) NO - NULL -
|
||||
assigned_to bigint(20) YES - NULL -
|
||||
last_update_time int(11) YES - NULL -
|
||||
|
||||
Since Miller handles TSV output, we can do as much or as little processing as we want in the SQL query, then send the rest on to Miller. This includes outputting as JSON, doing further selects/joins in Miller, doing stats, etc. etc.::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson --jlistwrap --jvstack cat
|
||||
[
|
||||
{
|
||||
"Field": "id",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "NO",
|
||||
"Key": "MUL",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "category",
|
||||
"Type": "varchar(256)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "is_permanent",
|
||||
"Type": "tinyint(1)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "assigned_to",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "last_update_time",
|
||||
"Type": "int(11)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
}
|
||||
]
|
||||
|
||||
$ mysql --database=mydb -B -e 'select * from mytable' > query.tsv
|
||||
|
||||
$ mlr --from query.tsv --t2p stats1 -a count -f id -g category,assigned_to
|
||||
category assigned_to id_count
|
||||
special 10000978 207
|
||||
special 10003924 385
|
||||
special 10009872 168
|
||||
standard 10000978 524
|
||||
standard 10003924 392
|
||||
standard 10009872 108
|
||||
...
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags.
|
||||
|
||||
SQL-input examples
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One use of NIDX (value-only, no keys) format is for loading up SQL tables.
|
||||
|
||||
Create and load SQL table::
|
||||
|
||||
mysql> CREATE TABLE abixy(
|
||||
a VARCHAR(32),
|
||||
b VARCHAR(32),
|
||||
i BIGINT(10),
|
||||
x DOUBLE,
|
||||
y DOUBLE
|
||||
);
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
bash$ mlr --onidx --fs comma cat data/medium > medium.nidx
|
||||
|
||||
mysql> LOAD DATA LOCAL INFILE 'medium.nidx' REPLACE INTO TABLE abixy FIELDS TERMINATED BY ',' ;
|
||||
Query OK, 10000 rows affected (0.07 sec)
|
||||
Records: 10000 Deleted: 0 Skipped: 0 Warnings: 0
|
||||
|
||||
mysql> SELECT COUNT(*) AS count FROM abixy;
|
||||
+-------+
|
||||
| count |
|
||||
+-------+
|
||||
| 10000 |
|
||||
+-------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mysql> SELECT * FROM abixy LIMIT 10;
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| a | b | i | x | y |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| pan | pan | 1 | 0.3467901443380824 | 0.7268028627434533 |
|
||||
| eks | pan | 2 | 0.7586799647899636 | 0.5221511083334797 |
|
||||
| wye | wye | 3 | 0.20460330576630303 | 0.33831852551664776 |
|
||||
| eks | wye | 4 | 0.38139939387114097 | 0.13418874328430463 |
|
||||
| wye | pan | 5 | 0.5732889198020006 | 0.8636244699032729 |
|
||||
| zee | pan | 6 | 0.5271261600918548 | 0.49322128674835697 |
|
||||
| eks | zee | 7 | 0.6117840605678454 | 0.1878849191181694 |
|
||||
| zee | wye | 8 | 0.5985540091064224 | 0.976181385699006 |
|
||||
| hat | wye | 9 | 0.03144187646093577 | 0.7495507603507059 |
|
||||
| pan | wye | 10 | 0.5026260055412137 | 0.9526183602969864 |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
|
||||
Aggregate counts within SQL::
|
||||
|
||||
mysql> SELECT a, b, COUNT(*) AS count FROM abixy GROUP BY a, b ORDER BY COUNT DESC;
|
||||
+------+------+-------+
|
||||
| a | b | count |
|
||||
+------+------+-------+
|
||||
| zee | wye | 455 |
|
||||
| pan | eks | 429 |
|
||||
| pan | pan | 427 |
|
||||
| wye | hat | 426 |
|
||||
| hat | wye | 423 |
|
||||
| pan | hat | 417 |
|
||||
| eks | hat | 417 |
|
||||
| pan | zee | 413 |
|
||||
| eks | eks | 413 |
|
||||
| zee | hat | 409 |
|
||||
| eks | wye | 407 |
|
||||
| zee | zee | 403 |
|
||||
| pan | wye | 395 |
|
||||
| wye | pan | 392 |
|
||||
| zee | eks | 391 |
|
||||
| zee | pan | 389 |
|
||||
| hat | eks | 389 |
|
||||
| wye | eks | 386 |
|
||||
| wye | zee | 385 |
|
||||
| hat | zee | 385 |
|
||||
| hat | hat | 381 |
|
||||
| wye | wye | 377 |
|
||||
| eks | pan | 371 |
|
||||
| hat | pan | 363 |
|
||||
| eks | zee | 357 |
|
||||
+------+------+-------+
|
||||
25 rows in set (0.01 sec)
|
||||
|
||||
Aggregate counts within Miller::
|
||||
|
||||
$ mlr --opprint uniq -c -g a,b then sort -nr count data/medium
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
|
||||
Pipe SQL output to aggregate counts within Miller::
|
||||
|
||||
$ mysql -D miller -B -e 'select * from abixy' | mlr --itsv --opprint uniq -c -g a,b then sort -nr count
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
wye pan 392
|
||||
zee eks 391
|
||||
zee pan 389
|
||||
hat eks 389
|
||||
wye eks 386
|
||||
hat zee 385
|
||||
wye zee 385
|
||||
hat hat 381
|
||||
wye wye 377
|
||||
eks pan 371
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
|
||||
Log-processing examples
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Another of my favorite use-cases for Miller is doing ad-hoc processing of log-file data. Here's where DKVP format really shines: one, since the field names and field values are present on every line, every line stands on its own. That means you can ``grep`` or what have you. Also it means not every line needs to have the same list of field names ("schema").
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags. But there's more you can do when not all the records have the same shape.
|
||||
|
||||
Writing a program -- in any language whatsoever -- you can have it print out log lines as it goes along, with items for various events jumbled together. After the program has finished running you can sort it all out, filter it, analyze it, and learn from it.
|
||||
|
||||
Suppose your program has printed something like this::
|
||||
|
||||
POKI_RUN_COMMAND{{cat log.txt}}HERE
|
||||
|
||||
Each print statement simply contains local information: the current timestamp, whether a particular cache was hit or not, etc. Then using either the system ``grep`` command, or Miller's ``having-fields``, or ``is_present``, we can pick out the parts we want and analyze them::
|
||||
|
||||
POKI_INCLUDE_AND_RUN_ESCAPED(10-1.sh)HERE
|
||||
POKI_INCLUDE_AND_RUN_ESCAPED(10-2.sh)HERE
|
||||
|
||||
Alternatively, we can simply group the similar data for a better look::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --opprint group-like log.txt}}HERE
|
||||
POKI_RUN_COMMAND{{mlr --opprint group-like then sec2gmt time log.txt}}HERE
|
||||
|
||||
More
|
||||
^^^^
|
||||
|
||||
Please see the <a href="reference.html">reference</a> for complete information, as well as the <a href="faq.html">FAQ</a> and the <a href="cookbook.html">cookbook</a> for more tips.
|
||||
855
docs/_static/basic.css
vendored
Normal file
855
docs/_static/basic.css
vendored
Normal file
|
|
@ -0,0 +1,855 @@
|
|||
/*
|
||||
* basic.css
|
||||
* ~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.section::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap : break-word;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox form.search {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="text"] {
|
||||
float: left;
|
||||
width: 80%;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||
float: left;
|
||||
width: 20%;
|
||||
border-left: none;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li div.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
table.indextable > tbody > tr > td > ul {
|
||||
padding-left: 0em;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.modindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
/* -- domain module index --------------------------------------------------- */
|
||||
|
||||
table.modindextable td {
|
||||
padding: 2px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
div.body {
|
||||
min-width: 450px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
a.brackets:before,
|
||||
span.brackets > a:before{
|
||||
content: "[";
|
||||
}
|
||||
|
||||
a.brackets:after,
|
||||
span.brackets > a:after {
|
||||
content: "]";
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink,
|
||||
caption:hover > a.headerlink,
|
||||
p.caption:hover > a.headerlink,
|
||||
div.code-block-caption:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
img.align-default, .figure.align-default {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-default {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
clear: right;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.admonition, div.topic, blockquote {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||
|
||||
div.sidebar > :last-child,
|
||||
div.topic > :last-child,
|
||||
div.admonition > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sidebar::after,
|
||||
div.topic::after,
|
||||
div.admonition::after,
|
||||
blockquote::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-default {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table caption span.caption-text {
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 5px;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.footnote td, table.footnote th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
table.citation td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
th > :first-child,
|
||||
td > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
th > :last-child,
|
||||
td > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* -- figures --------------------------------------------------------------- */
|
||||
|
||||
div.figure {
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.figure p.caption {
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-text {
|
||||
}
|
||||
|
||||
/* -- field list styles ----------------------------------------------------- */
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.field-name {
|
||||
-moz-hyphens: manual;
|
||||
-ms-hyphens: manual;
|
||||
-webkit-hyphens: manual;
|
||||
hyphens: manual;
|
||||
}
|
||||
|
||||
/* -- hlist styles ---------------------------------------------------------- */
|
||||
|
||||
table.hlist {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
table.hlist td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:first-child > :first-child,
|
||||
:not(li) > ul > li:first-child > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:last-child > :last-child,
|
||||
:not(li) > ul > li:last-child > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
ol.simple ol p,
|
||||
ol.simple ul p,
|
||||
ul.simple ol p,
|
||||
ul.simple ul p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple > li:not(:first-child) > p,
|
||||
ul.simple > li:not(:first-child) > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple p,
|
||||
ul.simple p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dl.footnote > dt,
|
||||
dl.citation > dt {
|
||||
float: left;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
dl.footnote > dd,
|
||||
dl.citation > dd {
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl.footnote > dd:after,
|
||||
dl.citation > dd:after {
|
||||
content: "";
|
||||
clear: both;
|
||||
}
|
||||
|
||||
dl.field-list {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(30%) auto;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
dl.field-list > dt:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
dl.field-list > dd {
|
||||
padding-left: 0.5em;
|
||||
margin-top: 0em;
|
||||
margin-left: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dl > dd:last-child,
|
||||
dl > dd:last-child > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt:target, span.highlighted {
|
||||
background-color: #0be54e;
|
||||
}
|
||||
|
||||
rect.highlighted {
|
||||
fill: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.sig-paren {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.guilabel, .menuselection {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.accelerator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.classifier {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
.classifier:before {
|
||||
font-style: normal;
|
||||
margin: 0.5em;
|
||||
content: ":";
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
pre, div[class*="highlight-"] {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
span.pre {
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
div[class*="highlight-"] {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tbody {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tr {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td.code {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.highlight .hll {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.highlight pre,
|
||||
table.highlighttable pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption + div {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
margin-top: 1em;
|
||||
padding: 2px 5px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div.code-block-caption code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos,
|
||||
div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-number {
|
||||
padding: 0.1em 0.3em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-text {
|
||||
}
|
||||
|
||||
div.literal-block-wrapper {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
code.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
code.xref, a code {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
span.eqno a.headerlink {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.math:hover a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
270
docs/_static/classic.css
vendored
Normal file
270
docs/_static/classic.css
vendored
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* classic.css_t
|
||||
* ~~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- classic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
html {
|
||||
/* CSS hack for macOS's scrollbar (see #1125) */
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #808080;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.document {
|
||||
/* CHANGE ME */
|
||||
background-color: #c0c0c0;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 230px;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
padding: 0 20px 30px 20px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #ffffff;
|
||||
width: 100%;
|
||||
padding: 9px 0 9px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #ffffff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
/* CHANGE ME */
|
||||
background-color: #808080;
|
||||
line-height: 30px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #800000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
color: #000000;
|
||||
font-size: 1.4em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
color: #000000;
|
||||
font-size: 1.3em;
|
||||
font-weight: normal;
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
margin: 5px 10px 10px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
/* CHANGE ME */
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- hyperlink styles ------------------------------------------------------ */
|
||||
|
||||
a {
|
||||
color: #800000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #800000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
background-color: #f2f2f2;
|
||||
font-weight: normal;
|
||||
/* CHANGE ME */
|
||||
color: #800000;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 20px -20px 10px -20px;
|
||||
padding: 3px 0 3px 10px;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 160%; }
|
||||
div.body h3 { font-size: 140%; }
|
||||
div.body h4 { font-size: 120%; }
|
||||
div.body h5 { font-size: 110%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.admonition p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition pre {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition ul, div.admonition ol {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px;
|
||||
background-color: unset;
|
||||
color: unset;
|
||||
line-height: 120%;
|
||||
border: 1px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #ecf0f3;
|
||||
padding: 0 1px 0 1px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
th, dl.field-list > dt {
|
||||
background-color: #ede;
|
||||
}
|
||||
|
||||
.warning code {
|
||||
background: #efc2c2;
|
||||
}
|
||||
|
||||
.note code {
|
||||
background: #d6d6d6;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background-color: #f4debf;
|
||||
border-top: 1px solid #ac9;
|
||||
border-bottom: 1px solid #ac9;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
color: #efefef;
|
||||
background-color: #1c4e63;
|
||||
}
|
||||
76
docs/_static/pygments.css
vendored
Normal file
76
docs/_static/pygments.css
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
pre { line-height: 125%; margin: 0; }
|
||||
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
||||
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
||||
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
|
||||
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
/* CHANGE ME */
|
||||
/*.highlight { background: #eeffcc; }*/
|
||||
.highlight { background: #c5b690; }
|
||||
.highlight .c { color: #408090; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #333333 } /* Generic.Output */
|
||||
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||
.highlight .m { color: #208050 } /* Literal.Number */
|
||||
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||
.highlight .nf { color: #06287e } /* Name.Function */
|
||||
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mb { color: #208050 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #208050 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
||||
113
docs/about.rst
Normal file
113
docs/about.rst
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
About
|
||||
=====
|
||||
|
||||
Miller is like awk, sed, cut, join, and sort for **name-indexed data such as
|
||||
CSV, TSV, and tabular JSON**. You get to work with your data using named
|
||||
fields, without needing to count positional column indices.
|
||||
|
||||
This is something the Unix toolkit always could have done, and arguably
|
||||
always should have done. It operates on key-value-pair data while the familiar
|
||||
Unix tools operate on integer-indexed fields: if the natural data structure for
|
||||
the latter is the array, then Miller's natural data structure is the
|
||||
insertion-ordered hash map. This encompasses a **variety of data formats**,
|
||||
including but not limited to the familiar CSV, TSV, and JSON. (Miller can handle
|
||||
**positionally-indexed data** as a special case.)
|
||||
|
||||
Features
|
||||
^^^^^^^^
|
||||
|
||||
* Miller is **multi-purpose**: it's useful for **data cleaning**, **data reduction**, **statistical reporting**, **devops**, **system administration**, **log-file processing**, **format conversion**, and **database-query post-processing**.
|
||||
|
||||
* You can use Miller to snarf and munge **log-file data**, including selecting out relevant substreams, then produce CSV format and load that into all-in-memory/data-frame utilities for further statistical and/or graphical processing.
|
||||
|
||||
* Miller complements **data-analysis tools** such as **R**, **pandas**, etc.: you can use Miller to **clean** and **prepare** your data. While you can do **basic statistics** entirely in Miller, its streaming-data feature and single-pass algorithms enable you to **reduce very large data sets**.
|
||||
|
||||
* Miller complements SQL **databases**: you can slice, dice, and reformat data on the client side on its way into or out of a database. (Examples <a href="10-min.html#SQL-input_examples">here</a> and <a href="10-min.html#SQL-output_examples">here</a>). You can also reap some of the benefits of databases for quick, setup-free one-off tasks when you just need to query some data in disk files in a hurry.
|
||||
|
||||
* Miller also goes beyond the classic Unix tools by stepping fully into our modern, **no-SQL** world: its essential record-heterogeneity property allows Miller to operate on data where records with different schema (field names) are interleaved.
|
||||
|
||||
* Miller is **streaming**: most operations need only a single record in memory at a time, rather than ingesting all input before producing any output. For those operations which require deeper retention (``sort``, ``tac``, ``stats1``), Miller retains only as much data as needed. This means that whenever functionally possible, you can operate on files which are larger than your system's available RAM, and you can use Miller in **tail -f** contexts.
|
||||
|
||||
* Miller is **pipe-friendly** and interoperates with the Unix toolkit
|
||||
|
||||
* Miller's I/O formats include **tabular pretty-printing**, **positionally indexed** (Unix-toolkit style), CSV, JSON, and others
|
||||
|
||||
* Miller does **conversion** between formats
|
||||
|
||||
* Miller's **processing is format-aware**: e.g. CSV ``sort`` and ``tac`` keep header lines first
|
||||
|
||||
* Miller has high-throughput **performance** on par with the Unix toolkit
|
||||
|
||||
* Not unlike <a href="http://stedolan.github.io/jq/">jq</a> (for JSON), Miller is written in portable, modern C, with **zero runtime dependencies**. You can download or compile a single binary, ``scp`` it to a faraway machine, and expect it to work.
|
||||
|
||||
Releases and release notes: <a href="https://github.com/johnkerl/miller/releases">https://github.com/johnkerl/miller/releases</a>.
|
||||
|
||||
Examples
|
||||
^^^^^^^^
|
||||
|
||||
Column select::
|
||||
|
||||
% mlr --csv cut -f hostname,uptime mydata.csv
|
||||
|
||||
Add new columns as function of other columns::
|
||||
|
||||
% mlr --nidx put '$sum = $7 < 0.0 ? 3.5 : $7 + 2.1*$8' *.dat
|
||||
|
||||
Row filter::
|
||||
|
||||
% mlr --csv filter '$status != "down" && $upsec >= 10000' *.csv
|
||||
|
||||
Apply column labels and pretty-print::
|
||||
|
||||
% grep -v '^#' /etc/group | mlr --ifs : --nidx --opprint label group,pass,gid,member then sort -f group
|
||||
|
||||
Join multiple data sources on key columns::
|
||||
|
||||
% mlr join -j account_id -f accounts.dat then group-by account_name balances.dat
|
||||
|
||||
Multiple formats including JSON::
|
||||
|
||||
% mlr --json put '$attr = sub($attr, "([0-9]+)_([0-9]+)_.*", "\1:\2")' data/*.json
|
||||
|
||||
Aggregate per-column statistics::
|
||||
|
||||
% mlr stats1 -a min,mean,max,p10,p50,p90 -f flag,u,v data/*
|
||||
|
||||
Linear regression::
|
||||
|
||||
% mlr stats2 -a linreg-pca -f u,v -g shape data/*
|
||||
|
||||
Aggregate custom per-column statistics::
|
||||
|
||||
% mlr put -q '@sum[$a][$b] += $x; end {emit @sum, "a", "b"}' data/*
|
||||
|
||||
Iterate over data using DSL expressions::
|
||||
|
||||
% mlr --from estimates.tbl put '
|
||||
for (k,v in $*) {
|
||||
if (is_numeric(v) && k =~ "^[t-z].*$") {
|
||||
$sum += v; $count += 1
|
||||
}
|
||||
}
|
||||
$mean = $sum / $count # no assignment if count unset
|
||||
'
|
||||
|
||||
Run DSL expressions from a script file::
|
||||
|
||||
% mlr --from infile.dat put -f analyze.mlr
|
||||
|
||||
Split/reduce output to multiple filenames::
|
||||
|
||||
% mlr --from infile.dat put 'tee > "./taps/data-".$a."-".$b, $*'
|
||||
|
||||
Compressed I/O::
|
||||
|
||||
% mlr --from infile.dat put 'tee | "gzip > ./taps/data-".$a."-".$b.".gz", $*'
|
||||
|
||||
Interoperate with other data-processing tools using standard pipes::
|
||||
|
||||
% mlr --from infile.dat put -q '@v=$*; dump | "jq .[]"'
|
||||
|
||||
Tap/trace::
|
||||
|
||||
% mlr --from infile.dat put '(NR % 1000 == 0) { print > stderr, "Checkpoint ".NR}'
|
||||
4
docs/circle.csv
Normal file
4
docs/circle.csv
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
color,shape,flag,index,quantity,rate
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
|
58
docs/conf.py
Normal file
58
docs/conf.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Miller'
|
||||
copyright = '2020, John Kerl'
|
||||
author = 'John Kerl'
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '5.9.1'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
#html_theme = 'alabaster'
|
||||
html_theme = 'classic'
|
||||
#html_theme = 'sphinxdoc'
|
||||
#html_theme = 'nature'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
11
docs/example.csv
Normal file
11
docs/example.csv
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,circle,1,16,13.8103,2.9010
|
||||
red,square,0,48,77.5542,7.4670
|
||||
purple,triangle,0,51,81.2290,8.5910
|
||||
red,square,0,64,77.1991,9.5310
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
yellow,circle,1,73,63.9785,4.2370
|
||||
yellow,circle,1,87,63.5058,8.3350
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
30
docs/index.rst
Normal file
30
docs/index.rst
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
Miller Docs v2 (under construction)
|
||||
===================================
|
||||
|
||||
Overview
|
||||
^^^^^^^^
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents
|
||||
|
||||
about
|
||||
10min
|
||||
|
||||
Using Miller
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Reference
|
||||
^^^^^^^^^
|
||||
|
||||
Background
|
||||
^^^^^^^^^^
|
||||
|
||||
Repository
|
||||
^^^^^^^^^^
|
||||
|
||||
Index
|
||||
^^^^^
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
43
docs/log.txt
Normal file
43
docs/log.txt
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
op=enter,time=1472819681
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
time=1472819690,batch_size=100,num_filtered=237
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A1,hit=1
|
||||
time=1472819705,batch_size=100,num_filtered=348
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
time=1472819713,batch_size=100,num_filtered=493
|
||||
op=cache,type=A9,hit=1
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=1
|
||||
time=1472819720,batch_size=100,num_filtered=554
|
||||
op=cache,type=A1,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=0
|
||||
op=cache,type=A4,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
time=1472819736,batch_size=100,num_filtered=612
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
time=1472819742,batch_size=100,num_filtered=728
|
||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
113
docs/poki
Executable file
113
docs/poki
Executable file
|
|
@ -0,0 +1,113 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$us = File.basename $0
|
||||
|
||||
require 'getoptlong'
|
||||
require 'fileutils'
|
||||
require 'json'
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
def main
|
||||
input_handle = $stdin
|
||||
output_handle = $stdout
|
||||
|
||||
input_handle.readlines.each do |content_line|
|
||||
|
||||
if content_line =~ /POKI_INCLUDE_ESCAPED\(([^)]+)\)HERE/
|
||||
included_file_name = $1
|
||||
include_escaped(included_file_name, output_handle)
|
||||
|
||||
elsif content_line =~ /POKI_INCLUDE_AND_RUN_ESCAPED\(([^)]+)\)HERE/
|
||||
included_file_name = $1
|
||||
cmd = File.readlines(included_file_name).join('')
|
||||
run_command(cmd, output_handle)
|
||||
|
||||
# # Page-content directive: run a script which generates HTML and print its output
|
||||
# elsif content_line =~ /POKI_RUN_UNESCAPED\(([^)]+)\)HERE/
|
||||
# included_file_name = $1
|
||||
# cmd = File.readlines(included_file_name).join('')
|
||||
# run_command(cmd, output_handle, false)
|
||||
#
|
||||
# # Page-content directive: include other file (do HTML escapes) and print its output
|
||||
# elsif content_line =~ /POKI_RUN_CONTENT_GENERATOR\(([^)]+)\)HERE/
|
||||
# cmd = $1
|
||||
# run_content_generator(cmd, output_handle)
|
||||
#
|
||||
# # Page-content directive: format as if included from a file.
|
||||
# elsif content_line =~ /POKI_CARDIFY\(([^)]+)\)HERE/
|
||||
# content_line = $1
|
||||
# cardify(content_line, output_handle, true)
|
||||
# elsif content_line =~ /POKI_CARDIFY{{([^)]+)}}HERE/
|
||||
# content_line = $1
|
||||
# cardify(content_line, output_handle, true)
|
||||
#
|
||||
# elsif content_line =~ /POKI_CARDIFY{{(.+)}}HERE/
|
||||
# content_line = $1
|
||||
# cardify(content_line, output_handle, true)
|
||||
#
|
||||
elsif content_line =~ /POKI_RUN_COMMAND{{(.+)}}HERE/
|
||||
cmd = $1
|
||||
run_command(cmd, output_handle)
|
||||
|
||||
# Page-content directive: include other file (do HTML escapes)
|
||||
# elsif content_line =~ /POKI_RUN_COMMAND_TOLERATING_ERROR{{(.+)}}HERE/
|
||||
# cmd = $1
|
||||
# run_command_tolerating_error(cmd, output_handle)
|
||||
|
||||
else
|
||||
output_handle.write(content_line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
def include_escaped(included_file_name, output_handle)
|
||||
write_card(File.readlines(included_file_name), output_handle, true)
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
def run_command(cmd, output_handle)
|
||||
cmd_output = `#{cmd} 2>&1`
|
||||
status = $?.to_i
|
||||
if status != 0
|
||||
raise "\"#{cmd}\" exited with non-zero code #{status}."
|
||||
end
|
||||
write_card(['$ '+cmd] + cmd_output.split(/\n/), output_handle)
|
||||
end
|
||||
|
||||
## ----------------------------------------------------------------
|
||||
#def run_command_tolerating_error(cmd, output_handle)
|
||||
# cmd_output = `#{cmd} 2>&1`
|
||||
# write_card(['$ '+cmd] + cmd_output.split(/\n/), output_handle, true)
|
||||
#end
|
||||
#
|
||||
## ----------------------------------------------------------------
|
||||
#def run_content_generator(cmd, output_handle)
|
||||
# cmd_output = `#{cmd} 2>&1`
|
||||
# status = $?.to_i
|
||||
# if status != 0
|
||||
# raise "\"#{cmd}\" exited with non-zero code #{status}."
|
||||
# end
|
||||
# output_handle.puts(cmd_output)
|
||||
#end
|
||||
#
|
||||
## ----------------------------------------------------------------
|
||||
#def cardify(content_line, output_handle)
|
||||
# write_card([content_line], output_handle)
|
||||
#end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
def write_card(content_lines, output_handle)
|
||||
content_lines.each do |content_line|
|
||||
output_handle.write(' ')
|
||||
output_handle.puts(content_line)
|
||||
end
|
||||
end
|
||||
|
||||
## ----------------------------------------------------------------
|
||||
#def html_escape_line(line)
|
||||
# line.gsub("&", "&").gsub("<", "<").gsub(">", ">").rstrip
|
||||
#end
|
||||
|
||||
# ================================================================
|
||||
main()
|
||||
5
docs/square.csv
Normal file
5
docs/square.csv
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
color,shape,flag,index,quantity,rate
|
||||
red,square,1,15,79.2778,0.0130
|
||||
red,square,0,48,77.5542,7.4670
|
||||
red,square,0,64,77.1991,9.5310
|
||||
purple,square,0,91,72.3735,8.2430
|
||||
|
5
docs/todo.txt
Normal file
5
docs/todo.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
* document _static CSS mods
|
||||
* do more such
|
||||
|
||||
* document (after rename) poki-filter and foo.rst.in -> foo.rst
|
||||
* implement that in the makefile
|
||||
4
docs/triangle.csv
Normal file
4
docs/triangle.csv
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
color,shape,flag,index,quantity,rate
|
||||
yellow,triangle,1,11,43.6498,9.8870
|
||||
purple,triangle,0,51,81.2290,8.5910
|
||||
purple,triangle,0,65,80.1405,5.8240
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue