Swift中使用正则表达式的一些方法
我使用Swift有段时间了,但最让人郁闷的是它还不能支持正则表达式.
先要说的是,这确实是门新语言,我在网站上有注释aradar(rdar://17257306forApplefolks).如果你也认同这一观点,请支持.
我所说的正则表达式指的是这种(Ruby代码):
ifname=~/ski$/ puts"#{name}isprobablypolish" end
如果要快速查询,可以使用=~操作符来返回匹配的结果.此外使用/pattern/syntax形式来直接使用正则.除了/符号需要转义,其它符号都不受影响:
url_pattern=/^https?:\/\/.*/
这比使用\\转义要好得多(这在正则里很常见).如果正则里使用了字符串,那看起来会很糟糕.这是Objective-C代码:
NSRegularExpression*regex=[NSRegularExpression regularExpressionWithPattern:@"\\s+\\w{4,10}\\s\\d+" options:0 error:nil];
转义每个\符号让代码可读性变差. 更别提额外类的创建了.当然,如果需要更强大的正则功能,那就得开发全套的特定实现类了. 但就一般情况来说(在脚本语言里很常见)有点小题大做.
Swift是怎么处理的?
Swift目前没有提供支持正则的语法和类,所以只能使用之前提到的NSRegularExpression来实现.
但是我们可以考虑使用swift的超强操作符来实现.考虑下面的场景:
classRegex{ letinternalExpression:NSRegularExpression letpattern:String init(_pattern:String){ self.pattern=pattern varerror:NSError? self.internalExpression=NSRegularExpression(pattern:pattern,options:.CaseInsensitive,error:&error) } functest(input:String)->Bool{ letmatches=self.internalExpression.matchesInString(input,options:nil,range:NSMakeRange(0,countElements(input))) returnmatches.count>0 } }
这在使用NSRegularExpression时需要提供大量的假设验证.如果用另一种方法就简单多了:
ifRegex("\\w{4}").test("ABCD"){ println("matchespattern") }
我们还是无可避免的得使用字符串转义,但比使用原生的NSRegularExpression好多了.
=~操作符
研究了一下StepChristopher的方法后,我想自己改造一下操作符功能.看起来挺简单的:
operatorinfix=~{}
这就定义了操作符的位置,就像操作两个元素时不是放在它们之间,而是一个元素之前或之后(就像++操作).下面定义一个使用该操作符的函数:
func=~(input:String,pattern:String)->Bool{ returnRegex(pattern).test(input) }
复杂的部分是现成的,我们只需要简单地调用.
最后,使用正则的测试结果如下:
letphoneNumber="(800)555-1111" ifphoneNumber=~"(?\\d{3})?\\s\\d{3}-\\d{4}"{ println("ThatlookslikeavalidUSphonenumber") }
我觉得这个结果很好,如果有天Apple发现了我的这个正则实现的语法/regex/literalsyntax,我很乐意提供支持.
更新
一个乐于助人的HackerNews评论家 指出一个更接近我想要的方向,但使用现有的API:
ifletmatch=name.rangeOfString("ski$",options:.RegularExpressionSearch){ println("\(name)isprobablypolish") }
的确,我不知道这个,并且看起来非常有用。