如何在Swift中使用正则表达式?

时间:2015-07-12 14:14:38

标签: regex swift

我在Swift中制作应用程序,我需要从字符串中捕获8个数字。 这是字符串: index.php?page=index&l=99182677

我的模式是: &l=(\d{8,})

这是我的代码:

var yourAccountNumber = "index.php?page=index&l=99182677"
let regex = try! NSRegularExpression(pattern: "&l=(\\d{8,})", options: NSRegularExpressionOptions.CaseInsensitive)
let range = NSMakeRange(0, yourAccountNumber.characters.count)
let match = regex.matchesInString(yourAccountNumber, options: NSMatchingOptions.Anchored, range: range)

首先,我不知道NSMatchingOptions的含义,在official Apple library,我没有得到所有.Anchored,.ReportProgress等内容。任何人都可以对此轻描淡写吗?

然后,当我print(match)时,该变量似乎没有任何内容([])。

我正在使用Xcode 7 Beta 3和Swift 2.0。

5 个答案:

答案 0 :(得分:8)

原始答案

这是一个可以用来获取捕获的组文本的函数:

import Foundation

extension String {
    func firstMatchIn(string: NSString!, atRangeIndex: Int!) -> String {
        var error : NSError?
        let re = NSRegularExpression(pattern: self, options: .CaseInsensitive, error: &error)
        let match = re.firstMatchInString(string, options: .WithoutAnchoringBounds, range: NSMakeRange(0, string.length))
        return string.substringWithRange(match.rangeAtIndex(atRangeIndex))
    }
}

然后:

var result = "&l=(\\d{8,})".firstMatchIn(yourAccountNumber, atRangeIndex: 1)

1中的atRangeIndex: 1将提取(\d{8,})捕获组捕获的文本。

NOTE1 :如果您计划在&l=之后提取8位数字,并且仅提取8位数字,那么您在限制量词中不需要,,因为{{1} }表示 8或更多。如果您打算只捕获8位数字,请更改为{8,}

NOTE2 :如果您的预期结果不在搜索范围的开头,则您希望避免使用{8}。见documentation

  

指定匹配仅限于搜索范围开头的匹配。

注3 :谈到“最简单”的事情,我会建议避免使用环视。环视通常会带来性能成本,如果您不想捕获重叠文本,我建议您使用捕获组。

SWIFT 2更新

我已经提出了一个函数,它将返回与所有捕获组的所有匹配(类似于PHP中的NSMatchingAnchored)。这是一种将它用于您的场景的方法:

preg_match_all

答案 1 :(得分:1)

使用NSString方法代替NSRegularExpression可能更容易。

var yourAccountNumber = "index.php?page=index&l=99182677"
println(yourAccountNumber) // index.php?page=index&l=99182677

let regexString = "(?<=&l=)\\d{8,}+"
let options :NSStringCompareOptions = .RegularExpressionSearch | .CaseInsensitiveSearch
if let range = yourAccountNumber.rangeOfString(regexString, options:options) {
    let digits = yourAccountNumber.substringWithRange(range)
    println("digits: \(digits)")
}
else {
    print("Match not found")
}

(?&lt; =&amp; l =)表示先于但不属于。

详细说明:

  

后面的断言。如果带括号的模式与当前输入位置之前的文本匹配,则为真,其中匹配的最后一个字符是当前位置之前的输入字符。不改变输入位置。与后视图案匹配的可能字符串的长度不得无限制(无*或+运算符。)

一般而言,没有仪表校样的后视镜的性能考虑只是过早优化。话虽如此,正则表达式中可能存在支持和反对环视的其他正当理由。

ICU用户指南:Regular Expressions

答案 2 :(得分:1)

考虑这个小NSRegularExpression extension,我写的只是为了从捕获组中提取(捕获括号)

然后你需要的是:

let yourAccountNumber = "index.php?page=index&l=99182677"
let pattern = "&l=(\\d{8,})"

if let capturingGroups = try! NSRegularExpression.capturingGroupsOfStringFirstMatch(yourAccountNumber, pattern: pattern){
    print(capturingGroups[0]) //prints '99182677'
}

答案 3 :(得分:1)

对于Swift 2,您可以使用此plt.errorbar(x[:2]+0.5,y[:2]+0.5,np.array(errors)[:2,:],fmt='d') plt.errorbar(x,y,np.array(errors),fmt='o') 的扩展名:

String

您可以通过以下方式获取帐号:

import Foundation

extension String {
    func firstMatchIn(string: NSString!, atRangeIndex: Int!) -> String {
        do {
            let re = try NSRegularExpression(pattern: self, options: NSRegularExpressionOptions.CaseInsensitive)
            let match = re.firstMatchInString(string as String, options: .WithoutAnchoringBounds, range: NSMakeRange(0, string.length))
            return string.substringWithRange(match!.rangeAtIndex(atRangeIndex))
        } catch {
            return ""
        }
    }
}

答案 4 :(得分:0)

NSMatchingOptions.Anchored替换为NSMatchingOptions()(无选项)