Regular expression and captures in an if condition


I am processing text one line at a time using regular expressions. The structure of the line determines how it is processed.

A concrete example:

A line: "Sample rate: 48000" I want to store the sample rate and move on to the next line
A line: "xrun detected" I want to increment a counter and move on to the next line.

Coming from Perl I would say:

if($line =~ /Sample rate: (\d+)/){
  $sample_rate = $1;

I want to do that in Rust, but I cannot figure out how. I have achieved my goal, but without any elegance

I have the regular expression:
sample_rate_re: Regex::new(r"Samplerate: (\d+)").unwrap()

if sample_rate_re.captures(line).is_some() {
  let caps = sample_rate_re.captures(line).unwrap(); 
  let sample_rate_text: &str = caps.get(1).map_or("0", |m| -> &str m.as_str());
  sample_rate = sample_rate_text.parse().unwrap();

But I am using the regular expression twice.

I would like to say:

if  caps = sample_rate_re.captures(line).unwrap() {
  let sample_rate_text: &str = caps.get(1).map_or("0", |m| -> &str m.as_str());

but that is not valid Rust.

Is there a way to do this?

Why don't you use .map?

1 Like

In general, any time you find yourself writing is_some() followed by unwrap(), you should use if let instead:

if let Some(caps) = sample_rate_re.captures(line) {
  let sample_rate_text: &str = caps.get(1).map_or("0", |m| -> &str m.as_str());

Another simplification is to just use caps[1], because your capturing group is not conditional. It is required to match in order for the regex overall to match.

sample_rate = caps[1].parse().unwrap();

Although you shouldn't unwrap the result of parse, because the regex can match more than what can be parsed into an integer. (Your Perl program likely has the same problem.)


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.