Struct fancy_regex::Regex
source · pub struct Regex { /* private fields */ }
Expand description
A compiled regular expression.
Implementations§
source§impl Regex
impl Regex
sourcepub fn new(re: &str) -> Result<Regex>
pub fn new(re: &str) -> Result<Regex>
Parse and compile a regex with default options, see RegexBuilder
.
Returns an Error
if the pattern could not be parsed.
sourcepub fn is_match(&self, text: &str) -> Result<bool>
pub fn is_match(&self, text: &str) -> Result<bool>
Check if the regex matches the input text.
Example
Test if some text contains the same word twice:
let re = Regex::new(r"(\w+) \1").unwrap();
assert!(re.is_match("mirror mirror on the wall").unwrap());
sourcepub fn find_iter<'r, 't>(&'r self, text: &'t str) -> Matches<'r, 't> ⓘ
pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> Matches<'r, 't> ⓘ
Returns an iterator for each successive non-overlapping match in text
.
If you have capturing groups in your regex that you want to extract, use the Regex::captures_iter() method.
Example
Find all words followed by an exclamation point:
let re = Regex::new(r"\w+(?=!)").unwrap();
let mut matches = re.find_iter("so fancy! even with! iterators!");
assert_eq!(matches.next().unwrap().unwrap().as_str(), "fancy");
assert_eq!(matches.next().unwrap().unwrap().as_str(), "with");
assert_eq!(matches.next().unwrap().unwrap().as_str(), "iterators");
assert!(matches.next().is_none());
sourcepub fn find<'t>(&self, text: &'t str) -> Result<Option<Match<'t>>>
pub fn find<'t>(&self, text: &'t str) -> Result<Option<Match<'t>>>
Find the first match in the input text.
If you have capturing groups in your regex that you want to extract, use the Regex::captures() method.
Example
Find a word that is followed by an exclamation point:
let re = Regex::new(r"\w+(?=!)").unwrap();
assert_eq!(re.find("so fancy!").unwrap().unwrap().as_str(), "fancy");
sourcepub fn find_from_pos<'t>(
&self,
text: &'t str,
pos: usize
) -> Result<Option<Match<'t>>>
pub fn find_from_pos<'t>(
&self,
text: &'t str,
pos: usize
) -> Result<Option<Match<'t>>>
Returns the first match in text
, starting from the specified byte position pos
.
Examples
Finding match starting at a position:
let re = Regex::new(r"(?m:^)(\d+)").unwrap();
let text = "1 test 123\n2 foo";
let mat = re.find_from_pos(text, 7).unwrap().unwrap();
assert_eq!(mat.start(), 11);
assert_eq!(mat.end(), 12);
Note that in some cases this is not the same as using the find
method and passing a slice of the string, see Regex::captures_from_pos() for details.
sourcepub fn captures_iter<'r, 't>(&'r self, text: &'t str) -> CaptureMatches<'r, 't> ⓘ
pub fn captures_iter<'r, 't>(&'r self, text: &'t str) -> CaptureMatches<'r, 't> ⓘ
Returns an iterator over all the non-overlapping capture groups matched in text
.
Examples
Finding all matches and capturing parts of each:
let re = Regex::new(r"(\d{4})-(\d{2})").unwrap();
let text = "It was between 2018-04 and 2020-01";
let mut all_captures = re.captures_iter(text);
let first = all_captures.next().unwrap().unwrap();
assert_eq!(first.get(1).unwrap().as_str(), "2018");
assert_eq!(first.get(2).unwrap().as_str(), "04");
assert_eq!(first.get(0).unwrap().as_str(), "2018-04");
let second = all_captures.next().unwrap().unwrap();
assert_eq!(second.get(1).unwrap().as_str(), "2020");
assert_eq!(second.get(2).unwrap().as_str(), "01");
assert_eq!(second.get(0).unwrap().as_str(), "2020-01");
assert!(all_captures.next().is_none());
sourcepub fn captures<'t>(&self, text: &'t str) -> Result<Option<Captures<'t>>>
pub fn captures<'t>(&self, text: &'t str) -> Result<Option<Captures<'t>>>
Returns the capture groups for the first match in text
.
If no match is found, then Ok(None)
is returned.
Examples
Finding matches and capturing parts of the match:
let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
let text = "The date was 2018-04-07";
let captures = re.captures(text).unwrap().unwrap();
assert_eq!(captures.get(1).unwrap().as_str(), "2018");
assert_eq!(captures.get(2).unwrap().as_str(), "04");
assert_eq!(captures.get(3).unwrap().as_str(), "07");
assert_eq!(captures.get(0).unwrap().as_str(), "2018-04-07");
sourcepub fn captures_from_pos<'t>(
&self,
text: &'t str,
pos: usize
) -> Result<Option<Captures<'t>>>
pub fn captures_from_pos<'t>(
&self,
text: &'t str,
pos: usize
) -> Result<Option<Captures<'t>>>
Returns the capture groups for the first match in text
, starting from
the specified byte position pos
.
Examples
Finding captures starting at a position:
let re = Regex::new(r"(?m:^)(\d+)").unwrap();
let text = "1 test 123\n2 foo";
let captures = re.captures_from_pos(text, 7).unwrap().unwrap();
let group = captures.get(1).unwrap();
assert_eq!(group.as_str(), "2");
assert_eq!(group.start(), 11);
assert_eq!(group.end(), 12);
Note that in some cases this is not the same as using the captures
method and passing a slice of the string, see the capture that we get
when we do this:
let re = Regex::new(r"(?m:^)(\d+)").unwrap();
let text = "1 test 123\n2 foo";
let captures = re.captures(&text[7..]).unwrap().unwrap();
assert_eq!(captures.get(1).unwrap().as_str(), "123");
This matched the number “123” because it’s at the beginning of the text of the string slice.
sourcepub fn captures_len(&self) -> usize
pub fn captures_len(&self) -> usize
Returns the number of captures, including the implicit capture of the entire expression.
sourcepub fn capture_names(&self) -> CaptureNames<'_> ⓘ
pub fn capture_names(&self) -> CaptureNames<'_> ⓘ
Returns an iterator over the capture names.
sourcepub fn replace<'t, R: Replacer>(&self, text: &'t str, rep: R) -> Cow<'t, str>
pub fn replace<'t, R: Replacer>(&self, text: &'t str, rep: R) -> Cow<'t, str>
Replaces the leftmost-first match with the replacement provided.
The replacement can be a regular string (where $N
and $name
are
expanded to match capture groups) or a function that takes the matches’
Captures
and returns the replaced string.
If no match is found, then a copy of the string is returned unchanged.
Replacement string syntax
All instances of $name
in the replacement text is replaced with the
corresponding capture group name
.
name
may be an integer corresponding to the index of the
capture group (counted by order of opening parenthesis where 0
is the
entire match) or it can be a name (consisting of letters, digits or
underscores) corresponding to a named capture group.
If name
isn’t a valid capture group (whether the name doesn’t exist
or isn’t a valid index), then it is replaced with the empty string.
The longest possible name is used. e.g., $1a
looks up the capture
group named 1a
and not the capture group at index 1
. To exert more
precise control over the name, use braces, e.g., ${1}a
.
To write a literal $
use $$
.
Examples
Note that this function is polymorphic with respect to the replacement. In typical usage, this can just be a normal string:
let re = Regex::new("[^01]+").unwrap();
assert_eq!(re.replace("1078910", ""), "1010");
But anything satisfying the Replacer
trait will work. For example,
a closure of type |&Captures| -> String
provides direct access to the
captures corresponding to a match. This allows one to access
capturing group matches easily:
let re = Regex::new(r"([^,\s]+),\s+(\S+)").unwrap();
let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
format!("{} {}", &caps[2], &caps[1])
});
assert_eq!(result, "Bruce Springsteen");
But this is a bit cumbersome to use all the time. Instead, a simple
syntax is supported that expands $name
into the corresponding capture
group. Here’s the last example, but using this expansion technique
with named capture groups:
let re = Regex::new(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)").unwrap();
let result = re.replace("Springsteen, Bruce", "$first $last");
assert_eq!(result, "Bruce Springsteen");
Note that using $2
instead of $first
or $1
instead of $last
would produce the same result. To write a literal $
use $$
.
Sometimes the replacement string requires use of curly braces to delineate a capture group replacement and surrounding literal text. For example, if we wanted to join two words together with an underscore:
let re = Regex::new(r"(?P<first>\w+)\s+(?P<second>\w+)").unwrap();
let result = re.replace("deep fried", "${first}_$second");
assert_eq!(result, "deep_fried");
Without the curly braces, the capture group name first_
would be
used, and since it doesn’t exist, it would be replaced with the empty
string.
Finally, sometimes you just want to replace a literal string with no
regard for capturing group expansion. This can be done by wrapping a
byte string with NoExpand
:
use fancy_regex::NoExpand;
let re = Regex::new(r"(?P<last>[^,\s]+),\s+(\S+)").unwrap();
let result = re.replace("Springsteen, Bruce", NoExpand("$2 $last"));
assert_eq!(result, "$2 $last");
sourcepub fn replace_all<'t, R: Replacer>(&self, text: &'t str, rep: R) -> Cow<'t, str>
pub fn replace_all<'t, R: Replacer>(&self, text: &'t str, rep: R) -> Cow<'t, str>
Replaces all non-overlapping matches in text
with the replacement
provided. This is the same as calling replacen
with limit
set to
0
.
See the documentation for replace
for details on how to access
capturing group matches in the replacement string.
sourcepub fn replacen<'t, R: Replacer>(
&self,
text: &'t str,
limit: usize,
rep: R
) -> Cow<'t, str>
pub fn replacen<'t, R: Replacer>(
&self,
text: &'t str,
limit: usize,
rep: R
) -> Cow<'t, str>
Replaces at most limit
non-overlapping matches in text
with the
replacement provided. If limit
is 0, then all non-overlapping matches
are replaced.
See the documentation for replace
for details on how to access
capturing group matches in the replacement string.