Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

rust - Regex remove entire line

I have a file that looks like:

mod one;
mod two;
mod three;

fn init() {}

Now I want to remove mod two using a simple Regex pattern, using the regex crate like:

let mod_pattern = regex::Regex::new("mod two;");
let mod_match = mod_pattern.captures(&file_contents).expect("Unable to get matches for mod two");
let mod_match_location = mod_match.get(0).expect("Unable to get mod two match group");

file_contents.replace_range(mod_match_location.start()..mod_match_location.end(), "");

This works, but it leaves my file looking like:

mod one;

mod three;

fn init() {}

I'm wondering how I can get rid of the entire line instead of leaving an empty line in its place. I realized I could do:

file_contents.replace_range(mod_match_location.start()-5 ..mod_match_location.end(), "");

and then run rustfmt but this assumes that the end user of my library is using 4 space indentation.

question from:https://stackoverflow.com/questions/66056740/regex-remove-entire-line

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to also match the following newline (and possible carriage return), so instead your pattern would look like r"mod two; ? ?". The newline is optional, as otherwise it won't match if "mod two;" is the last line in the file.

If you also want to support e.g. " mod two; ", i.e. extra horizontal whitespace. Then you can use [ ]* before and after, to optionally match zero-to-many spaces or tabs. To ensure that matching is done from the start of the line, you could use ^, which requires enabling multi-line mode with (?m). All in all, the final pattern could look like this:

r"(?m)^[ ]*mod two;[ ]*
?
?"

Note that you can't use s* in place of [ ]* as s also matches newlines. Thereby if mod two; was surrounded by blank lines, then these would be trimmed too.


I'm assuming you're using regex, because you want to do some more complex matching and substitution later. However, if not then you could instead use lines(), filter(), collect() and then join().

let file_contents = file_contents
    .lines()
    .filter(|&line| line.trim() != "mod two;")
    .collect::<Vec<_>>()
    .join("
");

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...