Swift中指定.backwards选项为何未从字符串末尾反向匹配?
问题解答
1. 关于Index(_rawBits: ...)的含义
Swift的String.Index是用于标记字符串字符位置的结构体,由于Swift字符串基于Unicode标量存储(并非简单的字节偏移),_rawBits是它内部用于存储位置信息的私有属性,属于底层实现细节,对外没有实际参考价值,只是打印时会显示这个内部值。
如果需要获取可读的位置偏移量,可以用distance(from:to:)方法计算从字符串起始索引到匹配位置的距离:
let offset = greeting.distance(from: greeting.startIndex, to: match.lowerBound) print("匹配位置的偏移量:\(offset)")
2. .backwards选项未生效的原因
问题出在你同时使用了.backwards和.regularExpression选项,两者组合后的行为和预期不符:
- 当不使用正则表达式时,
.backwards会让range(of:)从字符串末尾向前查找,返回第一个匹配到的结果(也就是最后一个出现的"o")。 - 当使用正则表达式时,
.backwards的作用被改变:它仅让正则引擎从搜索范围的末尾向开头扫描,但正则匹配逻辑仍然锚定在搜索范围的起始位置(整个字符串的开头)。对于"o"这种无锚定的简单模式,引擎还是会找到最左边的匹配项,所以无论加不加.backwards,结果都是第一个"o"。
解决方法
方法一:去掉正则表达式选项(推荐)
如果只是查找最后一个"o",完全不需要正则,直接使用.backwards即可:
import UIKit var greeting = "Hello, playground" if let match = greeting.range(of: "o", options: .backwards) { let lower = greeting.prefix(upTo: match.lowerBound) // 替代已废弃的substring(to:) let upper = greeting.suffix(from: match.lowerBound) // 替代已废弃的substring(from:) print("lower '\(lower)' upper '\(upper)'") }
这段代码会输出:lower 'Hello, playgr' upper 'ound',符合你的预期。
方法二:修改正则模式(必须用正则时)
如果必须使用正则查找最后一个"o",可以修改正则模式为匹配最后一个出现的目标字符:
if let match = greeting.range(of: "o(?=[^o]*$)", options: .regularExpression) { let lower = greeting.prefix(upTo: match.lowerBound) let upper = greeting.suffix(from: match.lowerBound) print("lower '\(lower)' upper '\(upper)'") }
这里的模式o(?=[^o]*$)利用正向预查,匹配后面没有其他"o"的目标字符,也就是最后一个"o"。
内容的提问来源于stack exchange,提问作者Grzegorz Adam Hankiewicz
相关产品推荐
相关产品推荐

