Swift 5.1 - 是否有一种干净的方法来处理子字符串/模式匹配的位置
Swift 5.1 - is there a clean way to deal with locations of substrings/ pattern matches
我对 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 中,这应该是 swift 并且很简单,但我发现这非常令人困惑。
有人可以帮忙做一下吗
查找子字符串的开始位置
提取子字符串末尾到文本末尾之间的所有文本
抱歉,如果这是微不足道的 - 但 Apple 文档感觉非常复杂,而且很多示例都是多年以前的。我似乎也找不到正则表达式的简单应用。
您可以使用 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"
您可以使用 string range(of: String) 方法来查找字符串的范围,获取其 upperBound 并从字符串的该位置搜索行尾:
游乐场测试:
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"
我对 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 中,这应该是 swift 并且很简单,但我发现这非常令人困惑。
有人可以帮忙做一下吗
查找子字符串的开始位置
提取子字符串末尾到文本末尾之间的所有文本
抱歉,如果这是微不足道的 - 但 Apple 文档感觉非常复杂,而且很多示例都是多年以前的。我似乎也找不到正则表达式的简单应用。
您可以使用 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"
您可以使用 string range(of: String) 方法来查找字符串的范围,获取其 upperBound 并从字符串的该位置搜索行尾:
游乐场测试:
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"