Swift 5.1 - есть ли чистый способ справиться с расположением подстрок / шаблонных совпадений - PullRequest
0 голосов
/ 02 мая 2020

Я очень, очень новичок в Swift и, по общему признанию, борюсь с некоторыми из его конструкций. Я должен работать с текстовым файлом и делать много манипуляций - вот пример, чтобы проиллюстрировать это:

Допустим, у меня есть такой текст (многострочный)

   Mary had a little lamb

   @name: a name

   @summary: a paragraph of text 

   {{something}}

   a whole bunch of multi-line text

  x----------------x

Я хочу чтобы иметь возможность делать простые вещи, такие как найти местоположение @name, затем разделить его, чтобы получить имя и так далее. Я сделал это в javascript, и это было довольно просто с использованием substr и регулярных выражений.

В быстром, который должен быть быстрым и легким, а что нет, я нахожу это чрезвычайно запутанным.

Может кто-нибудь помочь с тем, как можно сделать

  1. Найти место начала подстроки

  2. Извлечь весь текст от конца подстроки до конца текста

Извините, если это тривиально - но документация Apple кажется очень сложной, и многим примерам уже много лет. Я также не могу найти легкое применение регулярных выражений.

Ответы [ 2 ]

1 голос
/ 02 мая 2020

Вы можете использовать метод range (of: String) string, чтобы найти диапазон вашей строки, получить ее upperBound и найти конец строки из этой позиции строки:


Playground проверка:

let sentence = """
Mary had a little lamb

@name: a name

@summary: a paragraph of text

{{something}}

a whole bunch of multi-line text
"""

if let start = sentence.range(of: "@name:")?.upperBound,
    let end = sentence[start...].range(of: "\n")?.lowerBound {
    let substring = sentence[start..<end]
    print("name:", substring)
}

Если вам нужно получить строку оттуда до конца строки, вы можете использовать PartialRangeFrom:

if let start = sentence.range(of: "@summary:")?.upperBound {
    let substring = sentence[start...]
    print("summary:", substring)
}

Если вы обнаружите себя используя это, вы можете расширить StringProtocol и создать свой собственный метод:

 extension StringProtocol {
    func substring<S:StringProtocol,T:StringProtocol>(between start: S, and end: T, options: String.CompareOptions = []) -> SubSequence? {
        guard
            let lower = range(of: start, options: options)?.upperBound,
            let upper = self[lower...].range(of: end, options: options)?.lowerBound
        else { return nil }
        return self[lower..<upper]
    }
    func substring<S:StringProtocol>(after string: S, options: String.CompareOptions = []) -> SubSequence? {
        guard
            let lower = range(of: string, options: options)?.upperBound else { return nil }
        return self[lower...]
    }
}

Использование:

let name = sentence.substring(between: "@name:", and: "\n")  // " a name"

let sumary = sentence.substring(after: "@summary:")  // " a paragraph of text\n\n{{something}}\n\na whole bunch of multi-line text"

Вы также можете использовать регулярные выражения:

let name = sentence.substring(between: "@\\w+:", and: "\\n", options: .regularExpression)  // " a name"
1 голос
/ 02 мая 2020

Вы можете сделать это с range() и distance():

let str = "Example string"
let range = str.range(of: "amp")!
print(str.distance(from: str.startIndex, to: range.lowerBound)) // 2
let lastStr = str[range.upperBound...]
print(lastStr) // "le string"
...