record +
knit +
grid
One-liner DSL for shell-gei, record processing, and grid-based text transforms.
rkg is a one-liner oriented record/grid processor for text reshaping work.
It combines record-style operations for delimited text with grid-style operations for line-based patterns, so you can select, replace, reshape, transpose, rotate, and otherwise transform structured text from a compact command-line syntax.
For shell-friendly one-liners, the DSL should prefer a small punctuation set built
around ., :, ,, ;, and = so that common expressions stay readable in
bash/zsh without leaning too heavily on " or ().
r./rec.for record modeg./grid.for grid mode- method chaining with
. - pipeline chaining with
| - statement reset with
; - AWK-like separators:
fs,rs,ofs,ors -F/--field-separatorfor AWK-like initial field separator override-R/--record-separator,-O/--output-field-separator,-N/--output-record-separatorfor initial separator overrides- field selection, replace, explode, implode, groupby, reshape, flatten
- transpose, rotate, and ray/pattern mark operations for grid input
cargo install rkgcargo build --release$ rkg --help
Record/grid DSL processorprintf 'A,10;tokyo\nB:20;osaka\n' |
cargo run -- -F '[,:;]' 'r.p(1,2,3).ofs("|")'Shorthand:
printf 'A,10;tokyo\nB:20;osaka\n' |
cargo run -- -F '[,:;]' 'r.p:1,2,3.ofs=|'Existing commands:
printf 'A,10;tokyo\nB:20;osaka\n' |
awk -F'[,:;]' '{print $1 "|" $2 "|" $3}'r.fs(",").x(2,";").g(1,s(2)).ofs(",");
g.t().rt("r").m(p("K"),"orth","*")
Shorthand forms are also supported for shell-friendly one-liners:
mode.method:arg1,arg2.setting=value;mode.method:arg
mode.method | mode.method
g.t.rt:r
|pipes the previous stage output into the next stage when the right side starts withr./g.method(...)is the classic call formmethod:arg1,arg2is shorthand formethod(arg1,arg2)method=valueis shorthand for single-argument config-style calls likeofs("|")- bare
methodis shorthand for zero-argument calls liket() ;resets evaluation to the original stdin for the next statement group- only the last statement is printed by default
--print-allprints all statement results separated by----Fsets the initial record-modefsbefore the DSL runs, and accepts regex patterns-R,-O, and-Nset initialrs,ofs, andorsbefore the DSL runs- if
EXPRis omitted,rkgdefaults to record-mode passthrough with the initial CLI separators applied - when the shell would treat a character specially, quote the whole DSL as one argument
Sets the initial record-mode field separator from the CLI before any DSL method runs.
Example
Input:
A,10;tokyo
B:20;osaka
Command:
printf 'A,10;tokyo\nB:20;osaka\n' |
rkg -F '[,:;]' 'r.p(1,2,3).ofs("|")'Output:
A|10|tokyo
B|20|osaka
Shorthand:
printf 'A,10;tokyo\nB:20;osaka\n' |
rkg -F '[,:;]' 'r.p:1,2,3.ofs=|'Existing commands:
printf 'A,10;tokyo\nB:20;osaka\n' |
awk -F'[,:;]' '{OFS="|"}{print $1,$2,$3}'Passes shorthand output from one stage directly into the next stage with |.
Example
Input:
A 10
B 20
Command:
printf 'A 10\nB 20\n' |
rkg 'r.p:1,2.ofs=- | g.t'Existing commands:
printf 'A 10\nB 20\n' |
awk '{s=$1 "-" $2; for(i=1;i<=length(s);i++) col[i]=col[i] substr(s,i,1)} END{for(i=1; i in col; i++) print col[i]}'Output:
AB
--
12
00
Splits each record with the given regex instead of the default whitespace separator.
Example
Input:
A,10
B,20
Command:
printf 'A,10\nB,20\n' |
rkg 'r.fs(",")'Shorthand:
printf 'A,10\nB,20\n' |
rkg 'r.fs=,'Option only:
printf 'A,10\nB,20\n' |
rkg -F,Existing commands:
printf 'A,10\nB,20\n' |
awk -F',' '{print $1, $2}'Output:
A 10
B 20
Treats the given separator as the boundary between input records.
Example
Input:
A 10|B 20|
Command:
printf 'A 10|B 20|' |
rkg 'r.rs("|")'Shorthand:
printf 'A 10|B 20|' |
rkg 'r.rs=|'Option only:
printf 'A 10|B 20|' |
rkg -R'|'Existing commands:
printf 'A 10|B 20|' |
awk 'BEGIN{RS="\\|"} NF{print $0}'Output:
A 10
B 20
fs(re)input field separator regex, AWK-like (\s+by default)rs(sep)input record separator (\nby default)ofs(sep)output field separator (by default)ors(sep)output record separator (\nby default)p(...)/select(...)select fields, e.g.p(1,"3:")sb(re, rep)/replace(re, rep)regex replace per celln(start_or_AZ)/enum(...)prepend numbering orA-Zcycle labelsx(col, sep)/explode(...)split one field into multiple rowsi(key_col, val_col, join_sep?)/implode(...)collapse rows by keyg(key_col, agg...)/groupby(...)aggregate by keysh(mode, ...)/reshape(...)where mode isw2lorl2wf(template?)/flatten(...)flatten records; optional template like"{name}:{age}"
s(col)/sum(col)c()/count()mn(col)/min(col)mx(col)/max(col)a(col)/avg(col)med(col)/median(col)
fs(sep)optional cell separator; default is character gridrs(sep)/ofs(sep)/ors(sep)get(x, y)/get(p(...))returns a 1-cell grid from a 1-based coordinate or picked pointset(x, y, value)/set(p(...), value)overwrites one cell at a 1-based coordinate or picked pointline(origin, dir, values..., wrap(mode)?, skip(n)?)/ln(...)writes values along a direction or fill-mode from a coordinate or picked pointrev(mode, pad(value)?)/rv(...)reverses the grid horizontally, vertically, or both;pad(...)makes ragged rows rectangular firstt()/transpose()rt("r"|"l"|"180")/rotate(...)m(from, ray, put)marks along a ray (orth,diag,alldir,8);frommay be a literal orpick(value[, n])/p(value[, n])m(origin, "line", dir, values..., wrap(mode)?, skip(n)?)can reuse mark as a line-placement mode from one or more originsm(from, through_re, to, put)8-direction pattern mark, useful for reversi-like scans
r.p:1,3.ofs=|is equivalent tor.p(1,3).ofs("|")r.g:1,s:2is equivalent tor.g(1,s(2))g.get:3,2is equivalent tog.get(3,2)g.set:3,2,Xis equivalent tog.set(3,2,"X")g.rv:his equivalent tog.rev("h")g.rv:h,pad:"."is equivalent tog.rev("h",pad("."))g.ln:2,2,r,A,B,Cis equivalent tog.line(2,2,"r","A","B","C")g.ln:4,1,r,A,B,C,D,wrap:rowis equivalent tog.line(4,1,"r","A","B","C","D",wrap("row"))g.ln:1,1,fur,A,B,C,D,E,F,G,H,I,skip:1is equivalent tog.line(1,1,"fur","A","B","C","D","E","F","G","H","I",skip(1))g.m:p("K"),line,r,A,Bis equivalent tog.m(p("K"),"line","r","A","B")g.m:p("K",2),"diag","*"is equivalent tog.m(p("K",2),"diag","*")- shorthand is most useful for simple one-liners; regular
()calls remain available for anything that needs clearer quoting - the
Existing commandssnippets below are example-specific equivalents built from common shell tools, not drop-in general replacements for the full DSL
Changes the separator used when fields are joined for output.
Example
Input:
A 10
B 20
Command:
printf 'A 10\nB 20\n' |
rkg 'r.ofs(",")'Shorthand:
printf 'A 10\nB 20\n' |
rkg 'r.ofs=,'Option only:
printf 'A 10\nB 20\n' |
rkg -O,Existing commands:
printf 'A 10\nB 20\n' |
awk '{$1=$1; OFS=","; print}'Output:
A,10
B,20
Changes the separator used when output records are joined together.
Example
Input:
A 10
B 20
Command:
printf 'A 10\nB 20\n' |
rkg 'r.ors("|")'Shorthand:
printf 'A 10\nB 20\n' |
rkg 'r.ors=|'Option only:
printf 'A 10\nB 20\n' |
rkg -N'|'Existing commands:
printf 'A 10\nB 20\n' |
awk 'BEGIN{ORS="|"} {print $0}'Output:
A 10|B 20|
Keeps only the requested fields and removes the rest.
Example
Input:
A 10 tokyo
B 20 osaka
Command:
printf 'A 10 tokyo\nB 20 osaka\n' |
rkg 'r.p(1,3)'Shorthand:
printf 'A 10 tokyo\nB 20 osaka\n' |
rkg 'r.p:1,3'Existing commands:
printf 'A 10 tokyo\nB 20 osaka\n' |
awk '{print $1, $3}'Output:
A tokyo
B osaka
Replaces text matching the regex in every cell.
Example
Input:
A-10
B-20
Command:
printf 'A-10\nB-20\n' |
rkg 'r.sb("[0-9]","X")'Shorthand:
printf 'A-10\nB-20\n' |
rkg 'r.sb:[0-9],X'Existing commands:
printf 'A-10\nB-20\n' |
sed -E 's/[0-9]/X/g'Output:
A-XX
B-XX
Adds a numeric counter column to the front of each row.
Example
Input:
A 10
B 20
Command:
printf 'A 10\nB 20\n' |
rkg 'r.n(1)'Shorthand:
printf 'A 10\nB 20\n' |
rkg 'r.n:1'Existing commands:
printf 'A 10\nB 20\n' |
awk '{print NR, $0}'Output:
1 A 10
2 B 20
Uses alphabet labels instead of numbers and prepends them as a new first column.
Input:
A 10
B 20
C 30
Command:
printf 'A 10\nB 20\nC 30\n' |
rkg 'r.n("A-Z")'Shorthand:
printf 'A 10\nB 20\nC 30\n' |
rkg 'r.n:A-Z'Existing commands:
printf 'A 10\nB 20\nC 30\n' |
awk '{printf "%c %s\n", 64 + NR, $0}'Output:
A A 10
B B 20
C C 30
Splits one field into multiple rows while keeping the other columns as-is.
Example
Input:
A,10;20;30
B,7;8
Command:
printf 'A,10;20;30\nB,7;8\n' |
rkg -F, -O, 'r.x(2,";")'Shorthand:
printf 'A,10;20;30\nB,7;8\n' |
rkg -F, -O, 'r.x:2,";"'Existing commands:
printf 'A,10;20;30\nB,7;8\n' |
awk -F',' '{n=split($2, a, ";"); for (i=1; i<=n; i++) print $1 "," a[i]}'Output:
A,10
A,20
A,30
B,7
B,8
Merges rows with the same key by joining one value column into a single field.
Example
Input:
A 10
A 20
A 30
B 7
B 8
B 9
C 100
C 200
Command:
printf 'A 10\nA 20\nA 30\nB 7\nB 8\nB 9\nC 100\nC 200\n' |
rkg 'r.i(1,2,",")'Shorthand:
printf 'A 10\nA 20\nA 30\nB 7\nB 8\nB 9\nC 100\nC 200\n' |
rkg 'r.i:1,2,","'Existing commands:
printf 'A 10\nA 20\nA 30\nB 7\nB 8\nB 9\nC 100\nC 200\n' |
awk '!seen[$1]++{keys[++n]=$1} {vals[$1]=vals[$1] ? vals[$1] "," $2 : $2} END {for (i=1; i<=n; i++) print keys[i], vals[keys[i]]}'Output:
A 10,20,30
B 7,8,9
C 100,200
Groups rows by the key column and emits aggregate results per group.
Example
Input:
A,10;20;30
B,7;8
Command:
printf 'A,10;20;30\nB,7;8\n' |
rkg -F, -O, 'r.x(2,";").g(1,s(2))'Shorthand:
printf 'A,10;20;30\nB,7;8\n' |
rkg -F, -O, 'r.x:2,";".g:1,s:2'Existing commands:
printf 'A,10;20;30\nB,7;8\n' |
awk -F'[,;]' '{if (!seen[$1]++) keys[++n]=$1; for (i=2; i<=NF; i++) sum[$1]+=$i} END {for (i=1; i<=n; i++) print keys[i] "," sum[keys[i]]}'Output:
A,60
B,15
Turns wide columns into repeated long-form rows.
Example
Input:
name math eng
A 80 90
B 70 85
Command:
printf 'name math eng\nA 80 90\nB 70 85\n' |
rkg 'r.sh("w2l",2)'Shorthand:
printf 'name math eng\nA 80 90\nB 70 85\n' |
rkg 'r.sh:w2l,2'Existing commands:
printf 'name math eng\nA 80 90\nB 70 85\n' |
awk 'NR==1{for (i=2; i<=NF; i++) h[i]=$i; next} {for (i=2; i<=NF; i++) print $1, h[i], $i}'Output:
A math 80
A eng 90
B math 70
B eng 85
Turns repeated long-form rows back into a wide table.
Example
Input:
A math 80
A eng 90
B math 70
B eng 85
Command:
printf 'A math 80\nA eng 90\nB math 70\nB eng 85\n' |
rkg 'r.sh("l2w",2,3)'Shorthand:
printf 'A math 80\nA eng 90\nB math 70\nB eng 85\n' |
rkg 'r.sh:l2w,2,3'Existing commands:
printf 'A math 80\nA eng 90\nB math 70\nB eng 85\n' |
sort -k2,2 -k1,1 |
awk 'BEGIN{OFS=" "} !c[$2]++{col[++m]=$2} !r[$1]++{row[++n]=$1} {a[$1,$2]=$3} END{printf "key"; for(i=1;i<=m;i++) printf OFS col[i]; print ""; for(j=1;j<=n;j++){printf row[j]; for(i=1;i<=m;i++) printf OFS a[row[j],col[i]]; print ""}}'Output:
key eng math
A 90 80
B 85 70
Renders each data row as a single string using the header names in the template.
Example
Input:
name age
alice 20
bob 30
carol 25
dave 41
Command:
printf 'name age\nalice 20\nbob 30\ncarol 25\ndave 41\n' |
rkg 'r.f("{name}:{age}")'Shorthand:
printf 'name age\nalice 20\nbob 30\ncarol 25\ndave 41\n' |
rkg 'r.f:"{name}:{age}"'Existing commands:
printf 'name age\nalice 20\nbob 30\ncarol 25\ndave 41\n' |
awk 'NR>1 {print $1 ":" $2}'Output:
alice:20
bob:30
carol:25
dave:41
Sums the numeric values in the target column for each group.
Example
Input:
A 10
A 20
B 7
Command:
printf 'A 10\nA 20\nB 7\n' |
rkg 'r.g(1,s(2))'Shorthand:
printf 'A 10\nA 20\nB 7\n' |
rkg 'r.g:1,s:2'Existing commands:
printf 'A 10\nA 20\nB 7\n' |
awk '{c[$1]+=$2} END {for (k in c) print k, c[k]}' | sort
# or, with datamash:
printf 'A 10\nA 20\nB 7\n' |
datamash -s -g 1 sum 2Output:
A 30
B 7
Counts how many rows belong to each group.
Example
Input:
A 10
A 20
B 7
Command:
printf 'A 10\nA 20\nB 7\n' |
rkg 'r.g(1,c())'Shorthand:
printf 'A 10\nA 20\nB 7\n' |
rkg 'r.g:1,c'Existing commands:
printf 'A 10\nA 20\nB 7\n' |
awk '{print $1}' | uniq -c | awk '{print $2, $1}'
# or, with datamash:
printf 'A 10\nA 20\nB 7\n' |
datamash -s -g 1 count 1Output:
A 2
B 1
Takes the smallest numeric value in the target column for each group.
Example
Input:
A 10
A 20
A 15
B 7
B 12
C 3
C 9
Command:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g(1,mn(2))'Shorthand:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g:1,mn:2'Existing commands:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
sort -k1,1 -k2,2n | awk '!a[$1]++'
# or, with datamash:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
datamash -s -g 1 min 2Output:
A 10
B 7
C 3
Takes the largest numeric value in the target column for each group.
Example
Input:
A 10
A 20
A 15
B 7
B 12
C 3
C 9
Command:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g(1,mx(2))'Shorthand:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g:1,mx:2'Existing commands:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
sort -k1,1 -k2,2nr | awk '!a[$1]++'
# or, with datamash:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
datamash -s -g 1 max 2Output:
A 20
B 12
C 9
Computes the average numeric value in the target column for each group.
Example
Input:
A 10
A 20
A 15
B 7
B 12
C 3
C 9
Command:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g(1,a(2))'Shorthand:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g:1,a:2'Existing commands:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
awk '{sum[$1]+=$2; cnt[$1]++} END {for (k in sum) print k, sum[k] / cnt[k]}' |
sort
# or, with datamash:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
datamash -s -g 1 mean 2Output:
A 15
B 9.5
C 6
Computes the median numeric value in the target column for each group.
Example
Input:
A 10
A 20
A 15
B 7
B 12
C 3
C 9
Command:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g(1,med(2))'Shorthand:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
rkg 'r.g:1,med:2'Existing commands:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
awk '{a[$1][++n[$1]]=$2} END {for (k in a) {asort(a[k]); print k, n[k]%2 ? a[k][(n[k]+1)/2] : (a[k][n[k]/2]+a[k][n[k]/2+1])/2}}' |
sort
# or, with datamash:
printf 'A 10\nA 20\nA 15\nB 7\nB 12\nC 3\nC 9\n' |
datamash -s -g 1 median 2Output:
A 15
B 9.5
C 6
Treats each input row as separator-delimited cells instead of a character grid.
Example
Input:
a,b,c
d,e,f
Command:
printf 'a,b,c\nd,e,f\n' |
rkg -O'|' 'g.fs(",")'Shorthand:
printf 'a,b,c\nd,e,f\n' |
rkg -O'|' 'g.fs=,'Existing commands:
printf 'a,b,c\nd,e,f\n' |
awk -F',' '{print $1 "|" $2 "|" $3}'Output:
a|b|c
d|e|f
Treats the given separator as the boundary between grid rows.
Example
Input:
abc|def|ghi|
Command:
printf 'abc|def|ghi|' |
rkg 'g.rs("|")'Shorthand:
printf 'abc|def|ghi|' |
rkg 'g.rs=|'Option only:
printf 'abc|def|ghi|' |
rkg -R'|'Existing commands:
printf 'abc|def|ghi|' |
awk 'BEGIN{RS="\\|"} NF {print $0}'Output:
abc
def
ghi
Changes the separator used when cells are joined for each output row.
Example
Input:
abc
def
Command:
printf 'abc\ndef\n' |
rkg 'g.ofs("|")'Shorthand:
printf 'abc\ndef\n' |
rkg 'g.ofs=|'Option only:
printf 'abc\ndef\n' |
rkg -O'|'Existing commands:
printf 'abc\ndef\n' |
sed 's/./&|/g; s/|$//'Output:
a|b|c
d|e|f
Changes the separator used when output rows are joined together.
Example
Input:
abc
def
Command:
printf 'abc\ndef\n' |
rkg 'g.ors("---\n")'Shorthand:
printf 'abc\ndef\n' |
rkg 'g.ors="---\n"'Option only:
printf 'abc\ndef\n' |
rkg -N'---\n'Existing commands:
printf 'abc\ndef\n' |
awk 'BEGIN{ORS="---\n"} {print $0}'Output:
abc---
def---
Swaps rows and columns in the grid.
Example
Input:
abc
def
ghi
Command:
printf 'abc\ndef\nghi\n' |
rkg 'g.t()'Shorthand:
printf 'abc\ndef\nghi\n' |
rkg 'g.t'Existing commands:
printf 'abc\ndef\nghi\n' |
awk '{for (i=1; i<=length($0); i++) col[i]=col[i] substr($0, i, 1)} END {for (i=1; i in col; i++) print col[i]}'Output:
adg
beh
cfi
Rotates the grid 90 degrees clockwise.
Example
Input:
abc
def
ghi
Command:
printf 'abc\ndef\nghi\n' |
rkg 'g.rt("r")'Shorthand:
printf 'abc\ndef\nghi\n' |
rkg 'g.rt:r'Existing commands:
printf 'abc\ndef\nghi\n' |
awk '{rows[NR]=$0; if (length($0)>w) w=length($0)} END {for (i=1; i<=w; i++) {out=""; for (j=NR; j>=1; j--) out = out substr(rows[j], i, 1); print out}}'Output:
gda
heb
ifc
Rotates the grid by 180 degrees.
Input:
abc
def
ghi
Command:
printf 'abc\ndef\nghi\n' |
rkg 'g.rt("180")'Shorthand:
printf 'abc\ndef\nghi\n' |
rkg 'g.rt=180'Existing commands:
printf 'abc\ndef\nghi\n' |
awk '{rows[NR]=$0} END {for (i=NR; i>=1; i--) {out=""; for (j=length(rows[i]); j>=1; j--) out = out substr(rows[i], j, 1); print out}}'Output:
ihg
fed
cba
Marks all reachable cells along the specified ray directions from the source cell.
from can be a literal cell value or pick(value[, n]) / p(value[, n]), which selects the nth matching cell in top-to-bottom, left-to-right order.
Example
Input:
.......
.......
...K...
.......
.......
Command:
printf '.......\n.......\n...K...\n.......\n.......\n' |
rkg 'g.m(p("K"),"orth","*")'Nth match:
printf 'K....\n.....\n..K..\n.....\n....K\n' |
rkg 'g.m(p("K",2),"diag","*")'Existing commands:
printf '.......\n.......\n...K...\n.......\n.......\n' |
awk '{rows[NR]=$0; if ((p=index($0,"K"))>0) {ky=NR; kx=p}} END {for (y=1; y<=NR; y++) {out=""; for (x=1; x<=length(rows[y]); x++) {c=substr(rows[y], x, 1); if ((y==ky || x==kx) && !(y==ky && x==kx) && c==".") c="*"; out=out c} print out}}'Output:
...*...
...*...
***K***
...*...
...*...
Nth match output:
*...*
.*.*.
..K..
.*.*.
*...*
Marks only the matching middle cells when they are sandwiched between from and to.
Example
Input:
.......
.......
.XOOOX.
.......
.......
Command:
printf '.......\n.......\n.XOOOX.\n.......\n.......\n' |
rkg 'g.m("X","O","X","*")'Shorthand:
printf '.......\n.......\n.XOOOX.\n.......\n.......\n' |
rkg 'g.m:X,O,X,*'Existing commands:
printf '.......\n.......\n.XOOOX.\n.......\n.......\n' |
sed 's/XOOOX/X***X/'Output:
.......
.......
.X***X.
.......
.......
Reverses the grid horizontally, vertically, or both.
Use mode as h, v, or hv.
If rows have different widths, pad(value) can make them rectangular before reversing.
Example
Input:
abc
def
ghi
Command:
printf 'abc\ndef\nghi\n' |
rkg 'g.rev("h")'Shorthand:
printf 'abc\ndef\nghi\n' |
rkg 'g.rv:h'Output:
cba
fed
ihg
Pad example:
printf 'ab\ncde\n' |
rkg 'g.rev("h",pad("."))'Shorthand:
printf 'ab\ncde\n' |
rkg 'g.rv:h,pad:"."'Output:
.ba
edc
line(origin, dir, values..., wrap(mode)?, skip(n)?) / ln(origin, dir, values..., wrap(mode)?, skip(n)?)
Writes values along a direction or fill-mode from a coordinate or picked point.
One-way directions are right / r, left / l, up / u, down / d, ur, ul, dr, dl.
Centered directions are horiz / h, vert / v, diag_dr / xr, and diag_dl / xl, and they require an odd number of values so the middle value lands on the origin.
Fill modes are fill_ur / fur and fill_ul / ful.
wrap(mode) is optional and only works for one-way directions:
r/lwithwrap("row")u/dwithwrap("col")dr/ulwithwrap("diag_dr")dl/urwithwrap("diag_dl")
skip(n) is optional and only works for fill modes. It skips the first n cells in the fill traversal before writing values.
Example
Input:
.....
.....
.....
Command:
printf '.....\n.....\n.....\n' |
rkg 'g.line(2,2,"r","A","B","C")'Shorthand:
printf '.....\n.....\n.....\n' |
rkg 'g.ln:2,2,r,A,B,C'Output:
.....
.ABC.
.....
Wrapped shorthand:
printf '.....\n.....\n.....\n' |
rkg 'g.ln:4,1,r,A,B,C,D,wrap:row'Output:
...AB
CD...
.....
Diagonal example:
printf '.....\n.....\n.....\n.....\n.....\n' |
rkg 'g.line(2,2,"dr","C","O","D","E")'Output:
.....
.C...
..O..
...D.
....E
Diagonal shorthand:
printf '.....\n.....\n.....\n.....\n.....\n' |
rkg 'g.ln:2,2,dr,C,O,D,E'Diagonal wrap example:
printf '.....\n.....\n.....\n.....\n.....\n' |
rkg 'g.ln:3,3,dr,A,B,C,D,wrap:diag_dr'Output:
.D...
.....
..A..
...B.
....C
Top-edge diagonal example:
Coordinates are 1-based, so the top-left corner is (1,1).
printf '.....\n.....\n.....\n.....\n.....\n' |
rkg 'g.ln:1,1,dr,H,E,L,L,O'Output:
H....
.E...
..L..
...L.
....O
Second-row diagonal example:
printf '.....\n.....\n.....\n.....\n.....\n' |
rkg 'g.ln:1,2,dr,S,L,A,N'Output:
.....
S....
.L...
..A..
...N.
Fill-mode example:
printf '.....\n.....\n.....\n.....\n.....\n' |
rkg 'g.ln:1,1,fur,A,B,C,D,E,F,G,H,I,skip:1'Existing commands:
printf '.....\n.....\n.....\n.....\n.....\n' |
awk 'BEGIN{split("A B C D E F G H I", vals, " ")} {rows[NR]=$0} END {skip=1; n=0; for (d=0; d<10; d++) {for (x=0; x<=d; x++) {y=d-x; if (x<5 && y<5) cells[++n]=(x+1) "," (y+1)}} for (i=skip+1; i<=n && i-skip<=length(vals); i++) {split(cells[i], p, ","); x=p[1]; y=p[2]; row=rows[y]; rows[y]=substr(row,1,x-1) vals[i-skip] substr(row,x+1)} for (y=1; y<=5; y++) print rows[y]}'Output:
.BEI.
ADH..
CG...
F....
.....
Shifted fill-mode example:
printf '.....\n.....\n.....\n.....\n.....\n' |
rkg 'g.ln:1,1,fur,A,B,C,D,E,F,G,skip:3'Output:
..CG.
.BF..
AE...
D....
.....
You can also route the same behavior through mark mode:
printf '.....\n..K..\n.....\n' |
rkg 'g.m:p("K"),line,r,A,B'Multiple byte example:
seq -f 'printf " %%.s" {1..10};echo # %g' 1 7 |
bash |
rkg 'g.ln:1,1,fur,'$(echo "ウンコとこの子とボディビルそしてチンコ"|sed 's/\B/,/g')',skip:1' |
sed 's/$/\$/g'Output:
ンこボそ $
ウととルコ $
コ子ビン $
のィチ $
デて $
し $
$
Runs each statement against the original stdin, so later statements do not receive earlier output.
Example
Input:
A 10,20
B 7,8
Command:
printf 'A 10,20\nB 7,8\n' |
rkg --print-all 'r.x(2,",").g(1,s(2)); r.n(1)'Shorthand:
printf 'A 10,20\nB 7,8\n' |
rkg --print-all 'r.x:2,",".g:1,s:2; r.n:1'Existing commands:
{ printf 'A 10,20\nB 7,8\n' | awk '{split($2, a, ","); print $1, a[1] + a[2]}'; printf '%s\n' '---'; printf 'A 10,20\nB 7,8\n' | awk '{print NR, $0}'; }Output:
A 30
B 15
---
1 A 10,20
2 B 7,8
fsis treated as a regex for record mode, similar to AWKFS- CSV quoting is not implemented; this prototype is regex-split based
;resets to the original stdin; it does not pass the previous statement result to the next one- grid mode defaults to character cells;
g.fs(",")switches to separated cells