【问题标题】:Swift 5.1 - is there a clean way to deal with locations of substrings/ pattern matchesSwift 5.1 - 是否有一种干净的方法来处理子字符串/模式匹配的位置
【发布时间】:2020-08-16 14:24:35
【问题描述】:

我对 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 和正则表达式匹配非常简单。

在 swift 中,这应该是快速和简单的,但我发现这非常令人困惑。

有人可以帮忙看看怎么办吗

  1. 查找子字符串的开始位置

  2. 提取子字符串末尾到文本末尾之间的所有文本

对不起,如果这很琐碎 - 但是 Apple 文档感觉非常复杂,而且很多示例都是多年前的。我似乎也找不到简单的正则表达式应用。

【问题讨论】:

标签: swift string substring swift5


【解决方案1】:

您可以使用 string range(of: String) 方法来查找字符串的范围,获取其上界并从字符串的该位置搜索行尾:


游乐场测试:

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"

【讨论】:

  • 哇!这非常有用和有启发性,谢谢。我正在慢慢掌握它,但并不完全在那里。文档语法让我大吃一惊——当我快速阅读函数文档时,我很难将其转换为实际代码。也许这是一个习惯它并看到这样的例子的问题。
  • 如果需要查找所有出现的stackoverflow.com/a/61554215/2303865
【解决方案2】:

您可以使用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"

【讨论】:

  • OP 是 Swift 的新手。如果文本中没有“amp”范围,则会导致应用崩溃。
  • 我想我可以使用 .contains() 添加一些检查,然后再做一些... sigh
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 2011-06-25
相关资源
最近更新 更多