4

I want to extract a YAML block from a string. This block is not of typical YAML, and starts and ends with ---. I want the text in between these markers without the markers themselves. Below is a testing string (swift 4):

let testMe = """
--- 
# Metadata
title: hum
author: jecatatu
email: jecatatu@gmail.com
---
This is more text outside the yaml block
"""

In pure regex the pattern would be ---([\s\S]*?)---. My initial thought, since I am a beginner was to use VerbalExpressions, but I couldn't reproduce this pattern using Verbal Expression. The closest I got was:

let tester = VerEx()
    .find("---")
    .anything()
    .find("---")

How do I extract anything in between (but without) --- from a string using regex in Swift?

jww
  • 97,681
  • 90
  • 411
  • 885
lf_araujo
  • 1,991
  • 2
  • 16
  • 39
  • Possible duplicate of Swift [Get string between 2 strings in a string](https://stackoverflow.com/questions/31725424/swift-get-string-between-2-strings-in-a-string) – Martin R Oct 29 '17 at 08:12

2 Answers2

4

You can use String method

func range<T>(of aString: T, options mask: String.CompareOptions = default, range searchRange: Range<String.Index>? = default, locale: Locale? = default) -> Range<String.Index>? where T : StringProtocol

and use the regex pattern to find all characters between two strings from this SO answer:

let testMe = """
---
# Metadata
title: hum
author: jecatatu
email: jecatatu@gmail.com
---
This is more text outside the yaml block
"""

let pattern = "(?s)(?<=---\n).*(?=\n---)"
if let range = testMe.range(of: pattern, options: .regularExpression) {
    let text = String(testMe[range])
    print(text)
}

# Metadata
title: hum
author: jecatatu
email: jecatatu@gmail.com
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
1

You can use this regex :

let regex = "(?s)(?<=---).*(?=---)" 

Thanks to @leo that shows the correct regex in the accepted answer

And then with this function you can evaluate it:

 func matches(for regex: String, in text: String) -> [String] {

do {
    let regex = try NSRegularExpression(pattern: regex)
    let results = regex.matches(in: text,
                                range: NSRange(text.startIndex..., in: text))
    return results.map {
        String(text[Range($0.range, in: text)!])
    }
} catch let error {
    print("invalid regex: \(error.localizedDescription)")
    return []
}

}

Then use it

let matched = matches(for: regex, in: yourstring)
print(matched)

SourceSafe https://stackoverflow.com/a/27880748/1187415

developer_hatch
  • 15,898
  • 3
  • 42
  • 75
  • Yes but how to evaluate and extract this section with Swift? – lf_araujo Oct 29 '17 at 07:42
  • 1
    The "matches" method looks very familiar: https://stackoverflow.com/a/27880748/1187415 – Don't forget to add a link to the original page if you quote resources (https://stackoverflow.com/help/referencing) – Martin R Oct 29 '17 at 08:10
  • Did you test your proposed solution? That regex gives an *empty array* when applied to the string from the question. – Martin R Oct 29 '17 at 09:00
  • @MartinR thanks so much for the comment, it's correct and now I added the info that was missing – developer_hatch Oct 29 '17 at 09:06
  • @LeoDabus I used your regex, but just because it wasn't the most important in the question, it's a pretty easy one, but I will add where it comes from if you felt bad... – developer_hatch Oct 30 '17 at 01:25