ios - Swift 提取正则表达式匹配项

标签 ios regex string swift

我想从匹配正则表达式模式的字符串中提取子字符串。

所以我正在寻找这样的东西:

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 .

NSRangeRange<String.Index> 不兼容, 所以它阻止我使用 text.substringWithRange(...)

知道如何在没有太多代码行的情况下快速实现这个简单的事情吗?

最佳答案

即使 matchesInString()方法需要一个 String作为第一个参数, 它在内部与 NSString 一起工作,并且必须给出范围参数 使用 NSString长度而不是 Swift 字符串长度。否则会 对于“扩展字素簇”(例如“标志”)失败。

Swift 4 (Xcode 9) 开始,Swift 标准 库提供了在 Range<String.Index> 之间进行转换的函数 和 NSRange .

func matches(for regex: String, in text: String) -> [String] {

    do {
        let regex = try NSRegularExpression(pattern: regex)
        let results = regex.matches(in: text,
                                    range: NSRange(text.startIndex..., in: text))
        return results.map {
            String(text[Range($0.range, in: text)!])
        }
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

例子:

let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]

注意:强制展开 Range($0.range, in: text)!是安全的,因为 NSRange引用给定字符串的子字符串 text . 但是,如果您想避免它,请使用

        return results.flatMap {
            Range($0.range, in: text).map { String(text[$0]) }
        }

相反。


(Swift 3 及更早版本的旧答案:)

所以你应该将给定的 Swift 字符串转换为 NSString然后提取 范围。结果将自动转换为 Swift 字符串数组。

(Swift 1.2 的代码可以在编辑历史中找到。)

swift 2(Xcode 7.3.1):

func matchesForRegexInText(regex: String, text: String) -> [String] {

    do {
        let regex = try NSRegularExpression(pattern: regex, options: [])
        let nsString = text as NSString
        let results = regex.matchesInString(text,
                                            options: [], range: NSMakeRange(0, nsString.length))
        return results.map { nsString.substringWithRange($0.range)}
    } catch let error as NSError {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

例子:

let string = "🇩🇪€4€9"
let matches = matchesForRegexInText("[0-9]", text: string)
print(matches)
// ["4", "9"]

swift 3(Xcode 8)

func matches(for regex: String, in text: String) -> [String] {

    do {
        let regex = try NSRegularExpression(pattern: regex)
        let nsString = text as NSString
        let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
        return results.map { nsString.substring(with: $0.range)}
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

例子:

let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]

关于ios - Swift 提取正则表达式匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27880650/

相关文章:

string - 首字母大写Lua

java - 如何通过字符串声明已知其类型的变量类型

python - PythonKit错误“找不到Python库。设置PYTHON_LIBRARY环境变量和Python库的路径”

ios - 调整容器 View 的高度以匹配嵌入式 UITableView

java - 从正则表达式输出中删除空字符串

javascript - 正则表达式从字符串中去除纬度/经度

sql - PostgreSQL 中第一次出现空格时分割字符串?

ios - TextField 的 Pickerview

php - 由操作系统引起的潜在网站错误?

r - 为什么 gsubfn 会省略部分匹配项?