🚧 Very early stage
A command-line tool that can process text files ranging from a few hundred megabytes to several gigabytes with a single command. It uses a Ruby-like syntax and is about as fast as C.
Build from source:
git clone https://github.com/kojix2/crys
cd crys
make release=1 parallel=1
make installQ: Building from source? Why don’t you distribute pre-compiled binary files?
A: This tool only works in environments where the Crystal compiler is available. If the Crystal code cannot be compiled, Crys will not run. That’s why this approach works.
Basic form:
crys [options] 'CRYSTAL_CODE' [file ...]Process stdin line by line:
printf 'a\nb\n' | crys -n 'puts l.upcase'Assign the result back to l and print it:
printf 'a\nb\n' | crys -p 'l.upcase'Auto-split input:
printf 'a:b\nc:d\n' | crys -a -d: 'puts f[1]'Auto-split input with regex separator:
printf 'a: b\nc: d\n' | crys -a -d'/: +/' 'puts f[1]'Read a full JSON document from input:
printf '{"a":1}' | crys -r json 'puts JSON.parse(ARGF)["a"].as_i'Run setup and teardown code:
printf '1\n2\n3\n' | crys -A 'sum = 0' -n 'sum += l.to_i' -E 'puts sum'Edit files in place:
crys -I .bak -p 'l.gsub("foo", "bar")' file.txt
crys -i -p 'l.upcase' file.txtInspect generated code:
crys -D -p 'l.upcase'Filter lines with repeatable preconditions:
printf 'ok\nerror\nwarn\n' | crys -n --where 'l =~ /err|warn/' 'puts l'Use shortcut selectors and mappers:
printf 'a\nb\n' | crys -F 'l == "a"'
printf 'a\nb\n' | crys -M 'l.upcase'Bind split fields to names:
printf 'alice:20\nbob:30\n' | crys -a -d: -N name,age 'puts "#{name}:#{age}"'Use header-based access:
printf 'name,age\nalice,20\n' | crys -a -d, -H -M 'row["name"]'Aggregate quickly without boilerplate:
printf '1\n2\n3\n' | crys -S 'l.to_i'
printf 'ok\nerr\nwarn\n' | crys -W 'l =~ /err|warn/' -C
printf '1\nfoo\n3\n' | crys -W 'l =~ /^[0-9]+$/' -S 'l.to_i' -C-n: read input line by line. Exposesl,nr, andfnr-p,--print: same as-n, but assigns the body result back toland prints it-a,--auto-split: auto-splitlintofand exposenf-d,--delimiter SEP: field separator for-a. Prefix with/and suffix with/to use a regex:-d'/: +/'-N,--names NAMES: bind split fields to variable names. Example:-N name,count-W,--where COND: pre-filter condition in line mode. Repeatable, combined with AND-M,--map EXPR: shortcut for line mode mapping (puts(EXPR))-F,--filter COND: shortcut for line mode filtering (puts l if COND)-H,--header: treat first row as header and exposerowhash (requires-a)-S,--sum EXPR: sum expression across selected rows; exposes__crys_sum-C,--count: count selected rows; exposes__crys_count-i,--inplace: edit files in place without backup-I SUFFIX: edit files in place and keep backups withSUFFIX-r,--require LIB: addrequire "LIB"to the generated program. Resolution is done fromCRYS_HOME-A,--init CODE: insert code before the main body or loop-E,--final CODE: insert code after the main body or loop-D,--dump: print the generated Crystal code and exit-O LEVEL: build with optimization level (0,1,2,3,s,z)-R,--release: build withcrystal build --release--error-trace: build withcrystal build --error-trace--version: show tool version-h,--help: show help
l: current line, always chompedf: split fields, only with-anf: number of fields (f.size), only with-anr: record number (global, counts across all files)fnr: per-file record number (same asnrfor stdin, resets to 1 at each new file)path: current file path when reading files or editing in placerow:Hash(String, String)mapped from header columns, only with--header
crys builds and runs generated programs under CRYS_HOME (default: ~/.local/share/crys).
When you use -r LIB, dependency resolution is performed from this directory.
Typical setup:
export CRYS_HOME="$HOME/.local/share/crys"
mkdir -p "$CRYS_HOME"
cd "$CRYS_HOME"
shards init
vi shard.yml # Add your favorite shards
shards installThen:
printf '{"a":1}' | crys -r json 'puts JSON.parse(ARGF)["a"].as_i'Generated programs are cached under CRYS_HOME/cache and reused when the generated code and Crystal flags are unchanged.
-irequires at least one file-Mand-Fcannot be combined-M/-Fcannot be combined with explicitCRYSTAL_CODE-Nrequires-a-Hrequires-a-S/-Ccannot be combined with explicitCRYSTAL_CODE
Build:
makeRun unit tests:
make test-unitRun integration tests:
make test-integrationRun all tests:
make test