MST

星途 面试题库

面试题:Swift 正则表达式优化与复杂嵌套匹配

假设你有一段非常长且复杂的 HTML 文本,其中包含多层嵌套的标签,如 <div><span>content</span></div> 这种结构。现在需要用 Swift 正则表达式提取出所有 <span> 标签内的文本内容,且要处理好嵌套情况,避免误匹配。请写出完整的 Swift 代码实现,并详细解释正则表达式的设计思路以及如何优化匹配效率以应对长文本。
37.2万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试
import Foundation

func extractSpanText(from html: String) -> [String] {
    var results: [String] = []
    let pattern = "<span>(.*?)</span>"
    let regex = try! NSRegularExpression(pattern: pattern, options: [.dotMatchesLineSeparators])
    let range = NSRange(location: 0, length: html.utf16.count)
    regex.enumerateMatches(in: html, options: [], range: range) { match, _, _ in
        if let match = match, match.numberOfRanges > 1 {
            let spanRange = match.range(at: 1)
            if let spanText = (html as NSString).substring(with: spanRange) as String? {
                results.append(spanText)
            }
        }
    }
    return results
}

// 示例使用
let longHtmlText = "<div><span>content1</span><span>content2</span></div>"
let spanTexts = extractSpanText(from: longHtmlText)
print(spanTexts)

正则表达式设计思路

  1. <span></span> 界定:使用 <span></span> 来明确需要匹配的标签起始和结束位置。
  2. 非贪婪匹配:使用 .*? 来表示匹配尽可能少的字符,直到遇到第一个 </span>,这样可以处理多层嵌套标签,避免误匹配。例如在 <span><span>inner</span>outer</span> 这种嵌套结构中,能正确提取出内层和外层 <span> 标签内的文本。
  3. dotMatchesLineSeparators 选项:在初始化 NSRegularExpression 时使用 .dotMatchesLineSeparators 选项,这样 . 可以匹配换行符,从而处理跨多行的 <span> 标签内容。

优化匹配效率以应对长文本

  1. 非贪婪匹配:如上述,使用 .*? 非贪婪模式,减少不必要的回溯,提高匹配速度。
  2. 预编译正则表达式:将正则表达式预编译成 NSRegularExpression 对象,而不是每次都动态编译,提高多次匹配时的效率。
  3. 减少捕获组:尽量减少不必要的捕获组,在本示例中,只需要捕获 <span> 标签内的文本,所以只使用了一个捕获组 (.*?),避免过多捕获组带来的性能开销。