我想从匹配正则表达式模式的字符串中提取子字符串。
所以我在寻找这样的东西:
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)
}
}
我就是这么做的,我希望它能给斯威夫特带来一个新的视角。
在下面的例子中,我将获得[]之间的任何字符串
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)")
}
不幸的是,我发现公认的答案的解决方案不能在Linux的Swift 3上编译。下面是一个修改后的版本:
import Foundation
func matches(for regex: String, in text: String) -> [String] {
do {
let regex = try RegularExpression(pattern: regex, options: [])
let nsString = NSString(string: text)
let results = regex.matches(in: text, options: [], range: NSRange(location: 0, length: nsString.length))
return results.map { nsString.substring(with: $0.range) }
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
主要的区别是:
Linux上的Swift似乎需要在Foundation对象上删除NS前缀,而Swift本地没有对应的对象。(参见快速进化提案#86。)
Linux上的Swift还需要为RegularExpression初始化和matches方法指定options参数。
出于某种原因,在Linux上的Swift中,将String强制转换为NSString是行不通的,但在源中初始化一个新的NSString是可行的。
这个版本也适用于macOS / Xcode上的Swift 3,唯一的例外是你必须使用NSRegularExpression这个名字而不是RegularExpression。
在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
基本电话号码匹配
let phoneNumbers = ["+79990001101", "+7 (800) 000-11-02", "+34 507 574 147 ", "+1-202-555-0118"]
let match: (String) -> String = {
$0.replacingOccurrences(of: #"[^\d+]"#, with: "", options: .regularExpression)
}
print(phoneNumbers.map(match))
// ["+79990001101", "+78000001102", "+34507574147", "+12025550118"]