docs/src/repl.md
The Miller REPL (read-evaluate-print loop) is an interactive counterpart to record-processing using the put/filter language. (A REPL is anything that evaluates what you type into it -- like python with no arguments, or Ruby's irb, or node with no arguments, etc.)
Miller's REPL isn't a source-level debugger which lets you execute one source-code statement at a time -- however, it does let you operate on one record at a time. Further, it lets you use "immediate expressions", namely, you can interact with the Miller programming language without having to provide data from an input file.
<pre class="pre-highlight-in-pair"> <b>mlr repl</b> </pre> <pre class="pre-non-highlight-in-pair"> [mlr] 1 + 2 3 [mlr] apply([1,2,3,4,5], func(e) {return e ** 3}) [1, 8, 27, 64, 125] [mlr] :open example.csv [mlr] :read [mlr] $* { "color": "yellow", "shape": "triangle", "flag": "true", "k": 1, "index": 11, "quantity": 43.6498, "rate": 9.8870 } [mlr] :context FILENAME="example.csv",FILENUM=1,NR=1,FNR=1 </pre>Using put and filter, you can do the following as we've seen above:
--icsv), output format (e.g. --ojson), etc. using command-line flags.begin {...} blocks which are executed before the first record is read.end {...} blocks which are executed after the last record is read.func and subr.begin/end/func/subr.Using the REPL, by contrast, you get interactive control over those same steps:
--icsv), output format (e.g. --ojson), etc. using command-line flags.:, such as :help or :quit
or :open.:open at the Miller REPL.:read.$z = $x + $y)
using :write. This goes to the terminal; you can use :> {filename} to make writes
go to a file, or :>> {filename} to append.:reopen to go back to the start of the same file(s) you specified
with :open.:skip 10 or :skip until NR == 100 or
:skip until $status_code != 200.:process rather than :skip. Like :write, these go to the screen;
use :> {filename} or :>> {filename} to log to a file instead.begin {...} blocks; invoke them at will using :begin.end {...} blocks; invoke them at will using :end.func/subr; call them from other statements.:load.The input "record" by default is the empty map but you can do things like
$x=3, or unset $y, or $* = {"x": 3, "y": 4} to populate it. Or, :open foo.dat followed by :read to populate it from a data file.
Non-assignment expressions, such as 7 or true, operate as filter conditions
in the put DSL: they can be used to specify whether a record will or won't be
included in the output-record stream. But here in the REPL, they are simply
printed to the terminal, e.g. if you type 1+2, you will see 3.
< on a line by itself, then the code (taking care
for semicolons), then > on a line by itself. These will be executed immediately.<< on a line by itself, then the code, then >> on a line by
itself, the statements will be remembered for executing on records with
:main, as if you had done :load to load statements from a file.Use the REPL to look at arithmetic:
<pre class="pre-highlight-in-pair"> <b>mlr repl</b> </pre> <pre class="pre-non-highlight-in-pair"> [mlr] 6/3 2 [mlr] 6/5 1.2 [mlr] typeof(6/3) int [mlr] typeof(6/5) float </pre>Read the first record from a small file:
<pre class="pre-highlight-in-pair"> <b>mlr repl</b> </pre> <pre class="pre-non-highlight-in-pair"> [mlr] :open foo.dat [mlr] :read [mlr] :context FILENAME="foo.dat",FILENUM=1,NR=1,FNR=1 [mlr] $* { "a": "eks", "b": "wye", "i": 4, "x": 0.38139939387114097, "y": 0.13418874328430463 } [mlr] $z = $x + $i [mlr] :write a=eks,b=wye,i=4,x=0.38139939387114097,y=0.13418874328430463,z=4.381399393871141 </pre>Skip until deep into a larger file, then inspect a record:
<pre class="pre-highlight-in-pair"> <b>mlr repl --csv</b> </pre> <pre class="pre-non-highlight-in-pair"> [mlr] :open data/colored-shapes.csv [mlr] :skip until NR == 10000 [mlr] :r [mlr] $* { "color": "yellow", "shape": "circle", "flag": 1, "i": 496422, "u": 0.6530503199545348, "v": 0.23908588907834516, "w": 0.4799125551304738, "x": 6.379888206335166 } </pre>You can invoke mlr repl with the -v or -d flags to show parse trees for expressions you enter.
(The -v and -d flags differ only in the format they use to present the parse trees.)
For example, if you have any questions about operator precedence, you can check the
operator-precedence section -- or, you can
try it out and see for yourself:
No command-line-history-editing feature is built in but rlwrap mlr repl is a
delight. You may need brew install rlwrap, sudo apt-get install rlwrap,
etc. depending on your platform.
Suggestion: alias mrpl='rlwrap mlr repl' in your shell's startup file.
In your shell environment you can set the MLR_REPL_PS1 and MLR_REPL_PS2 environment variables if you like:
See also MLR_REPL_PS1_COLOR on the output-colorization page.
After mlr repl, type :help to see more about your options. In particular, :help examples.