Xeger (Xeger v0.1.0)
View SourceXeger turns a regex-like pattern into a stream of strings that match it.
This library is intentionally focused on a generatable subset of regular expressions. In particular, it does not support lookarounds or backreferences.
Supported syntax (subset)
- Literals:
abc - Escapes:
\(,\],\{, etc. - Dot:
.(matches one codepoint from:alphabet) - Alternation:
a|b|c - Grouping:
(ab|c) - Character classes:
[abc],[a-z],[^0-9] - Shorthands:
\d(0-9),\w(A-Z a-z 0-9 _),\s(whitespace) - Repetition:
*,+,?,{m},{m,},{m,n}
Quantifiers that are unbounded (*, +, {m,}) are, by default, genuinely
unbounded: stream/2 enumerates them lazily forever. Pass :max_repeat to
cap them instead.
Ordering
stream/2 enumerates matches in shortlex order:
shortest strings first, then (within the same length) a deterministic order.
Options
:max_repeat(default: none - unbounded) - caps*,+,{m,}at this many repeats; without it,stream/2on such a pattern is an infinite stream (safe to pipe intoEnum.take/2, unsafe to pipe into anything that consumes it eagerly, likeEnum.to_list/1orEnum.count/1):alphabet(default: printable ASCII) - set used for.and negated classes
Examples
iex> Xeger.take("a(b|c){2}\d", 6)
["abb0", "abb1", "abb2", "abb3", "abb4", "abb5"]
iex> Xeger.take("a*", 8)
["", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa"]
iex> Xeger.take("a*", 6, max_repeat: 3)
["", "a", "aa", "aaa"]
Summary
Functions
Compile a pattern into a %Xeger.Pattern{}.
Compile a pattern into a %Xeger.Pattern{} or raise.
Sanity helper: test a string against Elixir's Regex.
Generate a single random string matching a pattern, without enumerating the full match set.
Custom sigil for Xeger patterns.
Create an (often infinite) stream of matches.
Convenience: take n matches from a pattern.
Types
@type option() :: {:max_repeat, non_neg_integer()} | {:alphabet, [non_neg_integer()]} | {:seed, integer()}
Functions
@spec compile(binary(), [option()]) :: {:ok, Xeger.Pattern.t()} | {:error, binary()}
Compile a pattern into a %Xeger.Pattern{}.
Returns {:ok, pattern} or {:error, message}.
@spec compile!(binary(), [option()]) :: Xeger.Pattern.t()
Compile a pattern into a %Xeger.Pattern{} or raise.
Sanity helper: test a string against Elixir's Regex.
This is useful for tests and debugging (not used in generation).
@spec random(Xeger.Pattern.t() | binary(), [option()]) :: binary()
Generate a single random string matching a pattern, without enumerating the full match set.
Accepts either a binary pattern string or a compiled Pattern.t(). Pass
:seed for reproducible output; without it, each call draws fresh
randomness. :max_repeat and :alphabet behave as in stream/2 --
without :max_repeat, each repeat of an unbounded quantifier beyond its
minimum is a coin flip on whether to continue rather than a uniform draw
(see Xeger.Random for the exact distribution), so output length is
unbounded in principle but usually short.
Raises ArgumentError if the pattern (combined with :alphabet) has no
possible matches at all (e.g. a negated class that excludes the whole
alphabet).
Examples
iex> Xeger.random("a{3}", seed: 1)
"aaa"
iex> Xeger.random("[0-9]{4}", seed: 1) |> String.match?(~r/^[0-9]{4}$/)
true
@spec sigil_X( binary(), charlist() ) :: binary() | Xeger.Pattern.t() | Enumerable.t()
Custom sigil for Xeger patterns.
The ~X sigil generates one random string matching the pattern by
default -- see random/1. Use a modifier for the other forms:
Modifiers
- (none) - a random matching binary, via
random/1 c- compile only (returnsPattern.t(), viacompile!/1)s- stream mode (returnsEnumerable.t(), viacompile!/1andstream/1)
Examples
iex> ~X/[0-9]{4}/ |> String.match?(~r/^[0-9]{4}$/)
true
iex> pattern = ~X/[0-9]{3}/c
iex> Xeger.take(pattern, 5)
["000", "001", "002", "003", "004"]
iex> ~X/a+/s |> Enum.take(3)
["a", "aa", "aaa"]
@spec stream(Xeger.Pattern.t() | binary(), [option()]) :: Enumerable.t()
Create an (often infinite) stream of matches.
@spec take(Xeger.Pattern.t() | binary(), pos_integer(), [option()]) :: [binary()]
Convenience: take n matches from a pattern.
Accepts either a binary pattern string or a compiled Pattern.t().