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")
}
的确,我不知道这个,并且看起来非常有用。