How to match multiline regex?

Result: Record Start
Field: STRING, ordinal=0
Field: ANY, ordinal=1
SomeData,  Record End
#

Having the above, how to match that record so I can have match containing:
Field: STRING, ordinal=0
Field: ANY, ordinal=1
SomeData

Every line in the example is ended with newline char.

Thank you

It's hard to say exactly what you want here, but this will technically satisfy your requirements as stated:

$ cat main.rs
use regex::Regex;

fn main() {
    let haystack = "\
Result: Record Start
Field: STRING, ordinal=0
Field: ANY, ordinal=1
SomeData,  Record End
#
";
    let re = Regex::new(r"(?ms)Result: Record Start\n(.+?)^#$").unwrap();
    let Some(caps) = re.captures(haystack) else {
        eprintln!("NO MATCH");
        return;
    };
    println!("match: {:?}", &caps[1]);
}

$ cargo -q r
match: "Field: STRING, ordinal=0\nField: ANY, ordinal=1\nSomeData,  Record End\n"

The same regex will work if you're trying to match many of these records:

$ cat main.rs
use regex::Regex;

fn main() {
    let haystack = "\
Result: Record Start
Field: STRING, ordinal=0
Field: ANY, ordinal=1
SomeData,  Record End
#
Result: Record Start
Field: STRING, ordinal=1
Field: ANY, ordinal=2
SomeData,  Record End
#
Result: Record Start
Field: STRING, ordinal=2
Field: ANY, ordinal=3
SomeData,  Record End
#
";
    let re = Regex::new(r"(?ms)Result: Record Start\n(.+?)^#$").unwrap();
    for caps in re.captures_iter(haystack) {
        println!("match: {:?}", &caps[1]);
    }
}

$ cargo -q r
match: "Field: STRING, ordinal=0\nField: ANY, ordinal=1\nSomeData,  Record End\n"
match: "Field: STRING, ordinal=1\nField: ANY, ordinal=2\nSomeData,  Record End\n"
match: "Field: STRING, ordinal=2\nField: ANY, ordinal=3\nSomeData,  Record End\n"
1 Like

Hi and thank you for your reply.
It almosts satisfies my requirement :slight_smile:
I don't want that Record End in my match.
Could you also explain the meaning of
(?ms)
as well as
^#$

Thank you

If you want to change the endpoint, then you can just tweak the regex to match where you want it to end: (?ms)Result: Record Start\n(.+?)Record End\n#$. Of course, real world data might make your regex more complicated, especially if things like Record End appear in your data. But without a specification of your input format, it is totally unclear whether ad hoc parsing with a regex like this is appropriate or not.

(?ms) sets the flags m and s, which enable the multiline and dot_matches_new_line modes, respectively.

The ^#$ says to match a #, but only when it is preceded and followed by either the beginning of the string (for ^, the end of string for $), or a \n. You could also just write \n#\n, but whether you do that or not depends on whether you want the \n as part of your capture group or not.

1 Like

Thank you very much for your explanation and help.

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.