我想从匹配正则表达式模式的字符串中提取子字符串。
所以我在寻找这样的东西:
func matchesForRegexInText(regex: String!, text: String!) -> [String] {
???
}
这就是我得到的:
func matchesForRegexInText(regex: String!, text: String!) -> [String] {
var regex = NSRegularExpression(pattern: regex,
options: nil, error: nil)
var results = regex.matchesInString(text,
options: nil, range: NSMakeRange(0, countElements(text)))
as Array<NSTextCheckingResult>
/// ???
return ...
}
问题是,matchesInString提供给我一个NSTextCheckingResult数组,其中NSTextCheckingResult。range类型为NSRange。
NSRange与Range<String不兼容。索引>,它阻止我使用text。substringwithrange(…)
你知道如何在没有太多行代码的情况下实现这个简单的事情吗?
这是一个非常简单的解决方案,它返回一个包含匹配项的字符串数组
斯威夫特3。
internal func stringsMatching(regularExpressionPattern: String, options: NSRegularExpression.Options = []) -> [String] {
guard let regex = try? NSRegularExpression(pattern: regularExpressionPattern, options: options) else {
return []
}
let nsString = self as NSString
let results = regex.matches(in: self, options: [], range: NSMakeRange(0, nsString.length))
return results.map {
nsString.substring(with: $0.range)
}
}
上面的大多数解决方案只给出完全匹配,结果忽略了捕获组,例如:^\d+\s+(\d+)
为了获得预期的捕获组匹配,你需要(Swift4):
public extension String {
public func capturedGroups(withRegex pattern: String) -> [String] {
var results = [String]()
var regex: NSRegularExpression
do {
regex = try NSRegularExpression(pattern: pattern, options: [])
} catch {
return results
}
let matches = regex.matches(in: self, options: [], range: NSRange(location:0, length: self.count))
guard let match = matches.first else { return results }
let lastRangeIndex = match.numberOfRanges - 1
guard lastRangeIndex >= 1 else { return results }
for i in 1...lastRangeIndex {
let capturedGroupIndex = match.range(at: i)
let matchedString = (self as NSString).substring(with: capturedGroupIndex)
results.append(matchedString)
}
return results
}
}
我就是这么做的,我希望它能给斯威夫特带来一个新的视角。
在下面的例子中,我将获得[]之间的任何字符串
var sample = "this is an [hello] amazing [world]"
var regex = NSRegularExpression(pattern: "\\[.+?\\]"
, options: NSRegularExpressionOptions.CaseInsensitive
, error: nil)
var matches = regex?.matchesInString(sample, options: nil
, range: NSMakeRange(0, countElements(sample))) as Array<NSTextCheckingResult>
for match in matches {
let r = (sample as NSString).substringWithRange(match.range)//cast to NSString is required to match range format.
println("found= \(r)")
}
在Swift 5中返回所有匹配和捕获组的最快方式
extension String {
func match(_ regex: String) -> [[String]] {
let nsString = self as NSString
return (try? NSRegularExpression(pattern: regex, options: []))?.matches(in: self, options: [], range: NSMakeRange(0, nsString.length)).map { match in
(0..<match.numberOfRanges).map { match.range(at: $0).location == NSNotFound ? "" : nsString.substring(with: match.range(at: $0)) }
} ?? []
}
}
返回一个二维字符串数组:
"prefix12suffix fix1su".match("fix([0-9]+)su")
返回……
[["fix12su", "12"], ["fix1su", "1"]]
// First element of sub-array is the match
// All subsequent elements are the capture groups
非常感谢Lars Blumberg用Swift 4捕获小组和完整比赛的答案,这对我帮助很大。我还为那些确实希望出现错误的人添加了一些内容。当他们的正则表达式无效时localizedDescription响应:
extension String {
func matchingStrings(regex: String) -> [[String]] {
do {
let regex = try NSRegularExpression(pattern: regex)
let nsString = self as NSString
let results = regex.matches(in: self, options: [], range: NSMakeRange(0, nsString.length))
return results.map { result in
(0..<result.numberOfRanges).map {
result.range(at: $0).location != NSNotFound
? nsString.substring(with: result.range(at: $0))
: ""
}
}
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
}
对于我来说,localizedDescription作为错误有助于理解转义时发生了什么错误,因为它显示了swift试图实现的最终正则表达式。