mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-17 16:38:54 +00:00
Document a thousands-separator recipe for the DSL (#382)
Go's fmt package doesn't support the printf apostrophe flag (%'d), and Go's RE2 regex engine doesn't support the lookaheads used by the well-known sed/perl grouping recipe. Add a docs section showing a small user-defined DSL function which inserts thousands separators via repeated sub() application, handling negatives and decimal parts, and passing non-numeric values through unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
a63ea57359
commit
6d27931a45
2 changed files with 74 additions and 0 deletions
|
|
@ -84,3 +84,42 @@ x=0xffff,y=0xff,z=16711425
|
||||||
<pre class="pre-non-highlight-in-pair">
|
<pre class="pre-non-highlight-in-pair">
|
||||||
x=0xffff,y=0xff,z=0xfeff01
|
x=0xffff,y=0xff,z=0xfeff01
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
## Thousands separators
|
||||||
|
|
||||||
|
Some tools accept a `printf`-style apostrophe flag, e.g. `%'d`, to insert
|
||||||
|
locale-dependent thousands separators, formatting `12345` as `12,345`. Since
|
||||||
|
Miller's number formatting uses Go's [fmt](https://pkg.go.dev/fmt) package,
|
||||||
|
which doesn't support that flag, formats like `--ofmt "%'d"`,
|
||||||
|
`fmtnum($x, "%'d")`, and `format-values -i "%'d"` won't work. Likewise, the
|
||||||
|
well-known `sed`/`perl` recipe for inserting separators relies on regular-expression
|
||||||
|
lookaheads such as `(?=...)`, which [Go's regular-expression engine](reference-main-regular-expressions.md)
|
||||||
|
doesn't support.
|
||||||
|
|
||||||
|
You can, however, insert thousands separators with a small user-defined
|
||||||
|
[DSL function](reference-dsl-user-defined-functions.md) which applies
|
||||||
|
[`sub`](reference-dsl-builtin-functions.md#sub) until there's nothing left to
|
||||||
|
do. Digits are grouped from the left, so the decimal part (if any) is
|
||||||
|
untouched, and non-numeric values pass through unchanged:
|
||||||
|
|
||||||
|
<pre class="pre-highlight-in-pair">
|
||||||
|
<b>echo 'x=12345,y=1234567.8901,z=-987654321,s=hello' | mlr --opprint put '</b>
|
||||||
|
<b> func commify(n) {</b>
|
||||||
|
<b> s = string(n);</b>
|
||||||
|
<b> while (s =~ "^(-?[0-9]+)([0-9]{3})") {</b>
|
||||||
|
<b> s = sub(s, "^(-?[0-9]+)([0-9]{3})", "\1,\2");</b>
|
||||||
|
<b> }</b>
|
||||||
|
<b> return s;</b>
|
||||||
|
<b> }</b>
|
||||||
|
<b> for (k, v in $*) {</b>
|
||||||
|
<b> $[k] = commify(v);</b>
|
||||||
|
<b> }</b>
|
||||||
|
<b>'</b>
|
||||||
|
</pre>
|
||||||
|
<pre class="pre-non-highlight-in-pair">
|
||||||
|
x y z s
|
||||||
|
12,345 1,234,567.8901 -987,654,321 hello
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
To use a separator other than comma -- say, a space or a period -- simply
|
||||||
|
change the `,` in the `"\1,\2"` replacement string.
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,38 @@ GENMD-EOF
|
||||||
GENMD-RUN-COMMAND
|
GENMD-RUN-COMMAND
|
||||||
echo 'x=0xffff,y=0xff' | mlr put '$z=hexfmt($x*$y)'
|
echo 'x=0xffff,y=0xff' | mlr put '$z=hexfmt($x*$y)'
|
||||||
GENMD-EOF
|
GENMD-EOF
|
||||||
|
|
||||||
|
## Thousands separators
|
||||||
|
|
||||||
|
Some tools accept a `printf`-style apostrophe flag, e.g. `%'d`, to insert
|
||||||
|
locale-dependent thousands separators, formatting `12345` as `12,345`. Since
|
||||||
|
Miller's number formatting uses Go's [fmt](https://pkg.go.dev/fmt) package,
|
||||||
|
which doesn't support that flag, formats like `--ofmt "%'d"`,
|
||||||
|
`fmtnum($x, "%'d")`, and `format-values -i "%'d"` won't work. Likewise, the
|
||||||
|
well-known `sed`/`perl` recipe for inserting separators relies on regular-expression
|
||||||
|
lookaheads such as `(?=...)`, which [Go's regular-expression engine](reference-main-regular-expressions.md)
|
||||||
|
doesn't support.
|
||||||
|
|
||||||
|
You can, however, insert thousands separators with a small user-defined
|
||||||
|
[DSL function](reference-dsl-user-defined-functions.md) which applies
|
||||||
|
[`sub`](reference-dsl-builtin-functions.md#sub) until there's nothing left to
|
||||||
|
do. Digits are grouped from the left, so the decimal part (if any) is
|
||||||
|
untouched, and non-numeric values pass through unchanged:
|
||||||
|
|
||||||
|
GENMD-RUN-COMMAND
|
||||||
|
echo 'x=12345,y=1234567.8901,z=-987654321,s=hello' | mlr --opprint put '
|
||||||
|
func commify(n) {
|
||||||
|
s = string(n);
|
||||||
|
while (s =~ "^(-?[0-9]+)([0-9]{3})") {
|
||||||
|
s = sub(s, "^(-?[0-9]+)([0-9]{3})", "\1,\2");
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
for (k, v in $*) {
|
||||||
|
$[k] = commify(v);
|
||||||
|
}
|
||||||
|
'
|
||||||
|
GENMD-EOF
|
||||||
|
|
||||||
|
To use a separator other than comma -- say, a space or a period -- simply
|
||||||
|
change the `,` in the `"\1,\2"` replacement string.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue