Advanced Concepts¶
Expression Files (.mapc)¶
For very complex generations, you can author .mapc files instead of invoking the CLI. These files allow defining explicit aliases and sequentially joining outputs from multiple sub-expressions.
Syntax Overview
Comments start with
"# "(hash followed by a space) at the beginning of a line, or" # "(space + hash + space) when used inline.%define name pattern: Replace$name;withpatternthroughout the rest of the file.%include filename.txt: Expressly opens a file relative to the.mapcscript or an absolute path.Important: When you declare a
%include, that file is bound to the^placeholder in the very next expression line. It does not persist globally. You can declare multiple%definelines consecutively to bind to multiple^placeholders in the next expression.Any other (non-empty) line is treated as an expression.
Example payloads.mapc:
# Define Reusable Payload Aliases
%define DIGIT #[0-9]
%define BASE_URL (https://example.com/api/)
# Include a dictionary text file from previous runs
%include default_paths.txt
# Expression Generation
$BASE_URL;^\?id=$DIGIT; # Example: https://example.com/api/account?id=1
$BASE_URL;v$DIGIT; # Example: https://example.com/api/v1
Run using -f or --file:
mapchar -f payloads.mapc
Smart Skipping & Chunking¶
Large permutations quickly hit constraints. Mapchar addresses this through algorithmic seeking. Instead of creating combinations starting from A waiting until it hits your target, Mapchar calculates precisely where a specific target begins and resumes generation from there optimally.
You can segment workloads using -s/--start and -e/--end.
$ mapchar '/l{4}' -s abcd -e wxyz
abcd
abce
abcf
...
wxyz
This logic applies cleanly natively even when distributing across threads.
Multi-threading¶
You can specify multiple workers via -w <int>.
Mapchar intelligently delegates disjoint segments of the permutation space to each worker.
# using 3 different workers to write
$ mapchar '[/l/d]{5}' -w 3 -o output.txt
Value Bindings¶
Value bindings let you evaluate an expression once per output line and reuse the result any number of times within that line. Without bindings, two tokens always expand via cartesian product. With bindings, a definition and its references share the same drawn value — no additional combinations are introduced.
Syntax Overview
<@name=expr>— evaluateexpr, store the result undername, and output it.<@name>— output the value previously stored undername.
name must be a valid Python identifier. Referencing a name before it is defined raises an error.
Basic example
$ mapchar '<@d=/d>-<@d>'
0-0
1-1
...
9-9
Naively writing /d-/d would produce 100 lines (cartesian product of two independent digits).
With a binding, the digit is picked once and reused — 10 lines.
File placeholders inside bindings
The ^ placeholder works inside <@name=^>:
$ mapchar '<@x=^>:<@x>' words.txt
# apple:apple
# banana:banana
Repetition on bindings
Quantifiers {N}, {min,max}, and ? work on both definitions and references.
Repetition on the definition — the inner expression is repeated N times before being stored:
$ mapchar '<@n=/d{2}>_<@n>'
00_00
01_01
...
99_99
Repetition on the reference — the stored value is repeated N times in-place:
$ mapchar '<@d=/d>_<@d>{2}'
0_00
1_11
...
9_99
Multiple bindings
Each <@name=expr> is independent. Their values are combined via cartesian product with each other, but each pair of <@name=expr> / <@name> is internally consistent:
$ mapchar '<@a=[01]><@b=[xy]><@a><@b>'
0x0x
0y0y
1x1x
1y1y