user3118605
user3118605

Reputation: 41

Regex Non Greedy Matching across newlines

I am trying to match the following:

str = "---title: Some Title\ndate: 01/01/2012---\n\nSome other stuff---\n\n"

And I would like to get:

"title: Some Title\ndate: 01/01/2012"

So, the regex I came up with was:

~r/---(.+)---(.+)/s

It's unfortunately, being greed and matching:

"title: Some Title\ndate: 01/01/2012---\n\nSome other stuff"

I also tried the non-greedy operator and that failed too:

(~r/---(.+)---(.+)?.*/s

Any suggestions would be super helpful.

Thanks

Upvotes: 1

Views: 913

Answers (6)

Andie2302
Andie2302

Reputation: 4887

A more generic regex is:

(?:---)?(?<key>[a-z]+)\s*:\s*(?<value>(?!\\n).+?)(?:\\n|---|$)

It splits the match in key:value.

DEMO

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110675

If you ultimately want the title and date string, you may as well pull them out directly:

str.scan(/---title:\s+([^\n]+)\ndate:\s+(\d{2}\/\d{2}\/\d{4})/)
  #=> [["Some Title", "01/01/2012"]]

Upvotes: 0

Toto
Toto

Reputation: 91385

A perl way to do it:

#!/usr/bin/perl
use Modern::Perl;

my $str = "---title: Some Title\ndate: 01/01/2012---\n\nSome other stuff---\n\n";
$str =~ s/---(.+?)---.*?$/$1/s;
say $str;

Output:

title: Some Title
date: 01/01/2012

Upvotes: 0

sawa
sawa

Reputation: 168081

The right way here is not to try to match the part you want to extract, but match the part you want to throw away and use split.

s.split(/---\n*/)
#=> ["", "title: Some Title\ndate: 01/01/2012", "Some other stuff"]

str.split(/---\n*/)[1]
#=> "title: Some Title\ndate: 01/01/2012"

Upvotes: 0

Avinash Raj
Avinash Raj

Reputation: 174696

Use string.scan function like below.

> str = "---title: Some Title\ndate: 01/01/2012---\n\nSome other stuff---\n\n"
> str.scan(/---([\s\S]+?)---/)[0][0]
=> "title: Some Title\ndate: 01/01/2012"

Output of the above scan function is a two dimensional array is because of the existence of capturing group. [\s\S]+? Matches one or more space or non-space characters non-greedily. Note that this pattern would also match the line breaks (\n, \r).

Upvotes: 2

vks
vks

Reputation: 67968

---(?:(?!---).)*---

Try this.See demo.

https://regex101.com/r/fA6wE2/34

Upvotes: 0

Related Questions