“\“在字符串表示正则语义中的作用

在多数语言中,字符串中的"\"会作为转义字符串出现,用以将紧跟其后的字符转义,拓展字符的使用范围。但是在表示正则语义时,"\"会让一些使用场景显得很别扭.

别扭的"\\"

有这样一个场景:有一个文件名数组,需要从中筛选出以"json"结尾的文件名,在iOS中使用传统的正则匹配大概会这样:

Swift 复制代码
        let files = ["filea.txt", "fileb.json", "filec.json", "filed.pdf"];
        let regex = try? NSRegularExpression(pattern: ".*\\.json", options: NSRegularExpression.Options.caseInsensitive)
        let result = files.filter( { (regex?.matches(in: $0, range: NSRange(location: 0, length: $0.count)))?.isEmpty == false } )
        
        print("result:\(result)");

这时就会发现本来只是需要转义"."的"\"需要出现两次,为什么? 这里实际上经历了两个阶段的解析:

  • 所在语言的字符串解析:将"\\."解析为 \.
  • 正则引擎的正则解析: 将 \. 解析为 .

为什么必须是"\\"

在正则表达式(ERE)中, 由于"."有特殊元字符含义,所以使用其本来的意义时就需要使用"\."来表达.

而在swift中,"\"也是一个特殊含义的字符: 转义字符, 所以直接出现的"\"会被认为应该和紧跟其后的字符连起来组合称为一个新字符使用, 所以单独使用"\"会被认为是转义字符,而不是"\"本身,当需要表示"\"时就需要使用"\\"来表示一个真正意义上的"\". 所以在正则引擎中的 \. 在字符串中就会被表示成"\\.".

这里还有一个问题,在iOS的字符串中,常见的转义字符并不多:

\n \t \\ \" \r \0 \u{}

所以原则上讲,使用"\."来表示正则中的"."并没有歧义,那为什么不能直接使用"\."来表示呢?最要的原因是防止潜在的隐患.试想一下, 本来在字符串中出现"\"时,正常的逻辑是其后会出现一个需要被转义的字符,然后发现紧跟其后的是字符".", 并不是一个可以被转义的字符, 如果不报错就意味着"\anything"是一个合理的存在,在这种情况下编译器就无法进行正确的静态分析,无法提示错误,也会造成可读性下降(这他么难道是一个我不知道的转义字符). 所以, 不明语义的转义是不被允许的,这样就可以:

  • 防止拼写错误等隐藏bug;
  • 便于进行静态分析,提示错误,增强可阅读性;
  • 保持和其他主流语言(C/C++/Python/JavaScript/Java等)的逻辑一致性

其他实现方式

事实上,在swift中并不是必须使用这种看起来别扭的语法,有很多方式可以避开这种逻辑.

原始字符串

可以使用原始字符串来避开转义逻辑,上边的实现就可以使用

Swift 复制代码
        let regex = try? NSRegularExpression(pattern: #".*\.json"#, options: NSRegularExpression.Options.caseInsensitive)

来进行替换,这样就可以避开所在语言字符串的转义解析.

使用新的API

在Regex中已经直接使用"/pattern/" 来表示匹配模式,上边的实现可以修改为:

Swift 复制代码
 let result = files.filter({ $0.wholeMatch(of: /.*\.json/) != nil })

其他非正则的方式

可以借助于其他非正则封装的方式来实现,比如 `hasSuffix`之类.

相关推荐
大熊猫侯佩20 小时前
SwiftData 迁移深度指南:从入门到“填坑”(下集)
数据库·swift·编程语言
大熊猫侯佩20 小时前
SwiftData 迁移深度指南:从入门到“填坑”(上集)
数据库·swift·编程语言
多彩电脑1 天前
SwiftUI的导航界面的嵌套问题
开发语言·swift·设计语言
wjm0410061 天前
ios内存管理
ios·objective-c·swift·客户端开发
大熊猫侯佩2 天前
Swift 6.4 的 Ref / MutableRef 大揭秘:给值类型开一扇“安全的小窗”
ios·swift·编程语言
大熊猫侯佩3 天前
WWDC26 SwiftUI 进化之路:砸碎黑盒,彻底迎来开发自由!
ios·swiftui·swift
游戏开发爱好者83 天前
iPhone真机调试有哪些方法?一次定位推送权限问题时整理出来的几种方案
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
大熊猫侯佩3 天前
WWDC26 最被忽视的王炸:告别“伪并发”陷阱,Swift 6.4 的 async defer
ios·swift·编程语言
人月神话-Lee5 天前
WWDC26 深度解析:如何在 iOS 27 中打造“秒开”的相机体验
ios·swift·相机·wwdc·用户体验
Tr2e6 天前
🐱 从 0 到 1:用 Swift 手搓一个 macOS 桌面宠物(附源码)
macos·ios·swift