You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift正则表达式匹配含德语变音字符(Umlauten)文件失败求助

解决Swift正则匹配德语变音字符失败的问题

嘿,我帮你搞定这个德语变音字符(ö、ä、ü)的正则匹配问题!你遇到的问题大概率和Unicode规范化以及正则表达式的构建方式有关,locale设置只是次要因素,咱们一步步来解决:

核心问题分析

你手动拼接正则的方式容易踩两个坑:

  1. 如果stringArray里的字符串包含正则特殊字符(比如(、|、.),会直接破坏正则结构,导致匹配异常。
  2. 德语变音字符有两种Unicode表示形式:
    • 合成形式:比如ö是单个码点U+00F6
    • 分解形式:o(U+006F)加上分音符(U+0308)
      如果文件名里的字符和正则里的字符规范化形式不一致,哪怕看起来一样,也会匹配失败。

另外,locale设置主要影响locale相关的字符等价匹配(比如德语中ß和SS的等价),但不是你当前问题的核心,先解决上面两个问题再说。

修正后的代码方案

我把你的代码重构一下,解决这些问题:

import Foundation

// 1. 预处理字符串:转义正则特殊字符 + 统一Unicode规范化(NFC)
let somePrefix = "reis 8"
let stringArray = ["Ibedir", "Drölf "]
let escapedNormalizedStrings = stringArray.map {
    let normalized = $0.precomposedStringWithCanonicalMapping
    return NSRegularExpression.escapedPattern(for: normalized)
}

// 2. 安全构建正则表达式
let regexPattern = "\(somePrefix)_\(escapedNormalizedStrings.joined(separator: "|"))_w\\d_d\\d"

do {
    // 创建正则,启用Unicode相关选项
    let regex = try NSRegularExpression(pattern: regexPattern, options: [.useUnicodeWordBoundaries])
    
    let fileManager = FileManager()
    guard let enumerator = fileManager.enumerator(atPath: "/path/to/your/files") else {
        print("无法访问指定路径")
        return
    }
    
    // 3. 遍历文件时统一规范化文件名
    for case let fileName as String in enumerator {
        let normalizedFileName = fileName.precomposedStringWithCanonicalMapping
        let range = NSRange(normalizedFileName.startIndex..., in: normalizedFileName)
        
        if regex.firstMatch(in: normalizedFileName, options: [], range: range) != nil {
            print("\(fileName) found")
        }
    }
} catch {
    print("正则表达式构建失败:\(error.localizedDescription)")
}

关键改进点说明

  • 正则转义:用NSRegularExpression.escapedPattern(for:)自动转义字符串中的正则特殊字符,避免手动拼接导致的正则语法错误。
  • Unicode规范化:通过precomposedStringWithCanonicalMapping把所有字符串(包括正则里的和文件名)转成预合成NFC形式,确保变音字符的表示完全一致,从根源解决匹配失败的问题。
  • 使用NSRegularExpression API:相比String.range(of:options:),原生正则API更灵活,能更好地控制Unicode匹配行为。

关于Locale的补充

如果你需要支持德语locale下的特殊等价匹配(比如ß和SS视为相同),可以在创建正则时指定locale:

let germanLocale = Locale(identifier: "de_DE")
let regex = try NSRegularExpression(pattern: regexPattern, options: [.useUnicodeWordBoundaries], locale: germanLocale)

但这个不是必须的,除非你有这类特殊需求。

内容的提问来源于stack exchange,提问作者LarsGvB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:01:59