I want to use the regex
crate and capture numbers from a string.
let input = "abcd123efg";
let re = Regex::new(r"([0-9]+)").unwrap();
let cap = re.captures(e).unwrap().get(1).unwrap().as_str();
println!("{}", cap);
It worked if numbers exist in input
, but if numbers don't exist in input
I get the following error:
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value'
I want my program continue if the regex doesn't match. How can I handle this error?
You probably want to (re-)read the chapter on "Error Handling" in the Rust book. Error handling in Rust is mostly done via the types Result<T, E>
and Option<T>
, both representing an optional value of type T
with Result<T, E>
carrying additional information about the absence of the main value.
You are calling unwrap()
on each Option
or Result
you encounter. unwrap()
is a method saying: "if there is no value of type T
, let the program explode (panic)". You only want to call unwrap()
if an absence of a value is not expected and thus would be a bug! (NB: actually, the unwrap()
in your second line is a perfectly reasonable use!)
But you use unwrap()
incorrectly twice: on the result of captures()
and on the result of get(1)
. Let's tackle captures()
first; it returns an Option<_>
and the docs say:
If no match is found, then
None
is returned.
In most cases, the input string not matching the regex is to be expected, thus we should deal with it. We could either just match
the Option
(the standard way to deal with those possible errors, see the Rust book chapter) or we could use Regex::is_match()
before, to check if the string matches.
Next up: get(1)
. Again, the docs tell us:
Returns the match associated with the capture group at index
i
. Ifi
does not correspond to a capture group, or if the capture group did not participate in the match, thenNone
is returned.
But this time, we don't have to deal with that. Why? Our regex (([0-9]+)
) is constant and we know that the capture group exists and encloses the whole regex. Thus we can rule out both possible situations that would lead to a None
. This means we can unwrap()
, because we don't expect the absence of a value.
The resulting code could look like this:
let input = "abcd123efg";
let re = Regex::new(r"([0-9]+)").unwrap();
match re.captures(e) {
Some(caps) => {
let cap = caps.get(1).unwrap().as_str();
println!("{}", cap);
}
None => {
// The regex did not match. Deal with it here!
}
}
You can either check with is_match
or just use the return type of captures(e)
to check it (it's an Option<Captures<'t>>
) instead of unwrapping it, by using a match
(see this how to handle options).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With