7

I need to create a regular expression using the regex crate which includes a string passed as a command line argument to the program. The command line argument can contain $ and {}.

If I hard code the string as r"...", then it works fine, but if I use the command line argument as format!(r#"{}"#, arg_str), I get the following error (assuming arg_str = ${replace}) :

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Syntax(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
regex parse error:
    ${replace}
      ^
error: decimal literal empty
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
)', libcore/result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Simplified code example to demonstrate this issue:

extern crate regex;
use regex::Regex;

fn main() {
    let args: Vec<_> = std::env::args().collect();
    let ref arg_str = args[1];

    let re = Regex::new(format!(r#"{}"#, arg_str).as_str()).unwrap();
    println!("{:?}", re);
}

If this is run with a simple argument like replace, there is no error, but if I pass it something like ${replace}, I get the error mentioned above.

schaazzz
  • 568
  • 5
  • 19
  • I have currently resorted to passing a "pre-escaped" value as an arugment, e.g. `\$\{replace\}` – schaazzz May 26 '17 at 07:53
  • 5
    It's worth noting that `format!` absolutely does not behave how you appear to think it does. `"abc"` and `r"abc"` are not different kinds of things; they're both strings. It's just a question of how the compiler interprets their literal contents at compile time. Meaning that `format!("{}", ...)` and `format!(r#"{}"#, ...)` do the same thing. It's also worth noting that `format!("{}", value)` is really just a long-winded way of writing `value.to_string()`. – DK. May 26 '17 at 08:56
  • I understand now...my (incorrect) assumption was that it would convert it into a raw string since you can pass a raw string to Regex and not worry about escaping characters. Thank you for the explanation! – schaazzz May 26 '17 at 09:55

1 Answers1

14

The regex crate has a function escape which does what you need.

From the documentation:

Function regex::escape

pub fn escape(text: &str) -> String

Escapes all regular expression meta characters in text.
The string returned may be safely used as a literal in a regular expression.

So passing your arg_str through regex::escape should fix your problem.

belst
  • 2,285
  • 2
  • 20
  • 22