This library provides character filtering, numeric validation, and international number extraction for Rust strings. It builds on the Rust standard library with no regex dependency. It focuses on stripping or filtering characters by type and parsing numbers from free text, with full support for international decimal and thousands separator conventions (points, commas, spaces, apostrophes, middle dots).
- to-segments — Splits string slices and owned strings into vectors and extracts optional strings, pairs of optional strings.
| Feature | Default | Description |
|---|---|---|
cell_analysis |
no | Column-level decimal separator detection via analyze_cell, detect_column_format, and CellAnalysis |
Enable in Cargo.toml:
[dependencies]
alphanumeric = { version = "0.1", features = ["cell_analysis"] }- to-segments — Provides the
ToSegmentstrait for ergonomic string splitting with readable methods for common manipulation tasks. Also used internally byalphanumeric. - enclose-strings — Wrap or enclose strings in matching or complementary characters with optional escaping.
- simple-string-patterns — Provides simple methods to match and filter strings by simple patterns without regular expressions.
| Component position |
Meaning |
|---|---|
| strip_by_ ⇤ | Return a string without the specified character type(s) |
| filter_by_ ⇤ | Return a string with only the specified character type(s) |
| to_numbers ⇤ | Extract and parse numeric values from free text |
| to_numeric_strings ⇤ | Extract numeric substrings without parsing |
| _strict ⇥ | Variant accepting an explicit DecimalSeparator argument |
use alphanumeric::IsNumeric;
let num_str = "-1227.75";
assert!(num_str.is_numeric()); // true
let num_str = "12a34";
assert!(!num_str.is_numeric()); // false — contains non-numeric characteruse alphanumeric::StripCharacters;
const GBP_TO_EURO: f64 = 0.835;
let sample_str = "Price £12.50 each";
if let Some(price_gbp) = sample_str.to_first_number::<f64>() {
let price_eur = price_gbp / GBP_TO_EURO;
println!("The price in euros is {:.2}", price_eur);
}use alphanumeric::{StripCharacters, DecimalSeparator};
// Extract European-style numbers with commas as decimal separators
// and dots as thousand separators
let sample_str = "2.500 grammi di farina costa 9,90€ al supermercato.";
let numbers: Vec<f32> = sample_str.to_numbers_strict(DecimalSeparator::Comma);
if numbers.len() > 1 {
let weight_grams = numbers[0];
let price_euros = numbers[1];
let price_per_kg = price_euros / (weight_grams / 1000f32);
println!("Flour costs €{:.2} per kilo", price_per_kg); // €3.96
}use alphanumeric::StripCharacters;
// Extract 64-bit floats from a comma-separated list.
// Numbers within each segment are evaluated separately.
let sample_str = "34.2929,-93.701";
let numbers = sample_str.split_to_numbers::<f64>(",");
// yields vec![34.2929, -93.701]use alphanumeric::StripCharacters;
let source_str = "I spent £9999.99 on 2 motorbikes at the age of 72.";
assert_eq!(source_str.strip_non_numeric(), "9999.99 2 72");
assert_eq!(source_str.to_numbers::<f64>(), vec![9999.99, 2.0, 72.0]);
assert_eq!(source_str.to_first_number::<f32>().unwrap(), 9999.99f32);The DecimalSeparator enum controls how ambiguous separators are interpreted:
use alphanumeric::{StripCharacters, DecimalSeparator};
// US/UK format: commas as thousands, dot as decimal
let us_text = "Price: $1,234.56";
let nums: Vec<f64> = us_text.to_numbers();
assert_eq!(nums, vec![1234.56]);
// European format: dots as thousands, comma as decimal
let eu_text = "Kaufpreis: 1.500,50 EUR";
let nums: Vec<f64> = eu_text.to_numbers_strict(DecimalSeparator::Comma);
assert_eq!(nums, vec![1500.50]);
// French format: spaces as thousands, comma as decimal
let fr_text = "Le prix est 19 999,99 euros";
let nums: Vec<f64> = fr_text.to_numbers();
assert_eq!(nums, vec![19999.99]);
// Swiss format: apostrophes as thousands
let ch_text = "The cost is CHF 19'999.99";
let nums: Vec<f64> = ch_text.to_numbers();
assert_eq!(nums, vec![19999.99]);use alphanumeric::StripCharacters;
// Correct international separators to standard dot-decimal format
let european = "1.999.999,25";
assert_eq!(european.correct_numeric_string(), "1999999.25");
let english = "1,999,999.25";
assert_eq!(english.correct_numeric_string(), "1999999.25");use alphanumeric::{StripCharacters, CharType};
let sample_str = "Products: $9.99 per unit, £19.50 each, €15 only. Zürich café cañon";
let vowels_only = sample_str.filter_by_type(
CharType::Chars(&['a', 'e', 'i', 'o', 'u', 'é', 'ü', 'y'])
);
// yields "oueuieaoyüiaéao"
let lower_a_to_m = sample_str.filter_by_type(CharType::Range('a'..'n'));
// yields "dceieachlichcafca"
// Filter by multiple character categories
let lower_and_spaces = sample_str.filter_by_types(
&[CharType::Lower, CharType::Spaces]
);
// yields "roducts per unit each only ürich café cañon"use alphanumeric::StripCharacters;
let sample_str = "19 May 2021 ";
let without_spaces = sample_str.strip_spaces();
// yields "19May2021"use alphanumeric::{StripCharacters, CharType};
let sample_str = "Products: $9.99 per unit, £19.50 each, €15 only. Zürich café cañon";
let without_punctuation = sample_str.strip_by_type(CharType::Punctuation);
// yields "Products 999 per unit £1950 each €15 only Zürich café cañon"
let without_spaces_and_punct = sample_str.strip_by_types(
&[CharType::Spaces, CharType::Punctuation]
);
// yields "Products999perunit£1950each€15onlyZürichcafécañon"use alphanumeric::CharGroupMatch;
assert!("abc123".has_digits()); // true — contains digit characters
assert!(!"abc".has_digits()); // false
assert!("abc123".has_alphanumeric()); // true
assert!("abc".has_alphabetic()); // true
assert!("123".is_digits_only()); // true
assert!(!"12a3".is_digits_only()); // false
// Hexadecimal digit validation
assert!("1ec9F9a".is_digits_only_radix(16)); // trueRequires the cell_analysis feature.
use alphanumeric::{analyze_cell, detect_column_format, CellAnalysis, DecimalSeparator};
// Analyze individual cells
assert_eq!(analyze_cell("1 234,56"), CellAnalysis::Comma);
assert_eq!(analyze_cell("1'234.56"), CellAnalysis::Point);
assert_eq!(analyze_cell("1.234,56"), CellAnalysis::Comma);
// Detect format across a column of values
let cells = vec!["1 234,56", "2 345,78", "3 456,90"];
assert_eq!(detect_column_format(&cells, 10), DecimalSeparator::Comma);| Name | No. of methods | Description |
|---|---|---|
| IsNumeric | 1 | Check if a string can be parsed to an integer or float |
| StripCharacters | 17 | Strip unwanted characters by type, or extract vectors of numeric strings, integers or floats |
| CharGroupMatch | 6 | Validate strings with character classes: has_digits, has_alphanumeric, has_alphabetic, is_digits_only |
Strict check on a numeric string before using .parse::<T>(). Returns true for integers, negative numbers, and decimals with a single . separator.
use alphanumeric::IsNumeric;
assert!("123".is_numeric());
assert!("-456".is_numeric());
assert!("12.34".is_numeric());
assert!(!"12.34.56".is_numeric()); // multiple decimal points
assert!(!"".is_numeric()); // empty stringStrip unwanted characters by type or extract vectors of numeric strings, integers or floats without regular expressions.
| Method | Description |
|---|---|
strip_non_alphanum() |
Remove all non-alphanumeric characters |
strip_non_digits() |
Remove all non-digit characters |
strip_spaces() |
Remove whitespace characters |
strip_by_type(ct) |
Remove characters matching a specific CharType |
strip_by_types(cts) |
Remove characters matching any of the specified CharTypes |
filter_by_type(ct) |
Keep only characters matching a specific CharType |
filter_by_types(cts) |
Keep only characters matching any of the specified CharTypes |
to_numeric_strings() |
Extract numeric substrings using auto-detection |
to_numeric_strings_strict(sep) |
Extract numeric substrings with explicit DecimalSeparator |
to_numbers::<T>() |
Parse extracted numbers using auto-detection |
to_numbers_strict::<T>(sep) |
Parse extracted numbers with explicit DecimalSeparator |
to_first_number::<T>() |
Extract the first parsed number, or None |
to_first_number_strict::<T>(sep) |
Extract the first parsed number with explicit separator |
split_to_numbers::<T>(pattern) |
Split by pattern and extract the first number from each segment |
strip_non_numeric() |
Extract numeric strings and join them with spaces |
correct_numeric_string() |
Normalize separators to standard dot-decimal format |
correct_numeric_string_strict(sep) |
Normalize separators with explicit DecimalSeparator |
Validate strings with character classes.
| Method | Description |
|---|---|
has_digits() |
Contains at least one ASCII digit |
has_digits_radix(radix) |
Contains at least one digit in the given radix |
has_alphanumeric() |
Contains at least one alphanumeric character |
has_alphabetic() |
Contains at least one alphabetic character |
is_digits_only() |
All characters are ASCII digits |
is_digits_only_radix(radix) |
All characters are digits in the given radix |
Controls how ambiguous separators (dots, commas) are interpreted when extracting numbers.
| Variant | Meaning |
|---|---|
Point |
Treat . as the decimal separator (US, UK, Asia, etc.) |
Comma |
Treat , as the decimal separator (many European, Latin American, African countries) |
Auto |
Intelligently detect based on separator patterns (recommended for mixed contexts) |
Defines categories, sets or ranges of characters as well as single characters. Used with strip_by_type, strip_by_types, filter_by_type, and filter_by_types.
| Variant | Arguments | Meaning |
|---|---|---|
Any |
— | Matches any character |
DecDigit |
— | Match 0–9 only (is_ascii_digit) |
Digit |
(u32) |
Match digit with the specified radix (e.g. 16 for hexadecimal) |
Numeric |
— | Match number-like characters in the decimal base (excludes . and -) |
AlphaNum |
— | Match any alphanumeric characters (is_alphanumeric) |
Lower |
— | Match lower case letters (is_lowercase) |
Upper |
— | Match upper case letters (is_uppercase) |
Alpha |
— | Match any letters in most supported alphabets (is_alphabetic) |
Spaces |
— | Match whitespace (is_whitespace) |
Punctuation |
— | Match ASCII punctuation (is_ascii_punctuation) |
Char |
(char) |
Match a single character |
Chars |
(&[char]) |
Match an array of characters |
Range |
(Range<char>) |
Match a range, e.g. 'a'..'d' includes a, b, c but not d |
Between |
(char, char) |
Match characters between the specified bounds, inclusive on both ends |
Result of analyzing a single cell's decimal separator format, returned by analyze_cell().
| Variant | Meaning |
|---|---|
Point |
Clearly uses . as decimal separator |
Comma |
Clearly uses , as decimal separator |
Either |
Ambiguous — could use either format |
None |
No decimal separator present |
analyze_cell(txt: &str) -> CellAnalysis
Analyze a single numeric string to determine which decimal separator convention it uses. Examines the positions of dots, commas, spaces, apostrophes and middle dots to make a determination.
detect_column_format(cells: &[&str], max_scan: usize) -> DecimalSeparator
Scan a column of cell values and detect the predominant decimal separator format. Stops early when the format becomes clear (3+ votes with a 2+ lead). Useful for batch processing tabular data where the format is consistent within a column.
uses_decimal_comma(txt: &str, enforce_euro_mode: bool) -> bool
Detect if a numeric string uses European format with , as the decimal separator and dots as thousand separators. When enforce_euro_mode is true, a single comma is always treated as a decimal separator; otherwise it may be interpreted as a thousands separator depending on position.