iOS NSRegularExpression与条件模板

时间:2016-10-12 18:22:19

标签: ios regex swift nsregularexpression

我正在尝试将电话号码格式化为(###)### - #### 格式。

我正在使用以下正则表达式替换模板

let regex = try NSRegularExpression(pattern: "([0-9]{3})([0-9]{1,3})([0-9]{0,4})")
regex.stringByReplacingMatches(
    in: rawNumber, 
    options: .reportCompletion, 
    range: NSRange(location: 0, length: rawNumber.characters.count), 
    withTemplate: "($1) $2-$3"
)

问题是我的模板字符串包含硬编码的-,如果找不到第三个捕获组$ 3,则不应该出现。

例如

rawNumber = "5125"

当我真正想要格式为(512) 5-时,

会被替换为(512) 5,因为除非找到第三个捕获组,否则我不希望显示-。< / p>

例如,我希望有一种方法可以将模板制作为:

"($1) $2if$3{-}$3"

4 个答案:

答案 0 :(得分:2)

您可以为条件替换编写自己的NSRegularExpression子类:

class PhoneNumberConverter: NSRegularExpression {
    override func replacementString(for result: NSTextCheckingResult, in string: String, offset: Int, template templ: String) -> String {
        //Assuming `pattern` has always 3 captures
        if result.rangeAt(3).length == 0 {
            //$3 isn't found
            return super.replacementString(for: result, in: string, offset: offset, template: "($1) $2")
        } else {
            return super.replacementString(for: result, in: string, offset: offset, template: "($1) $2-$3")
        }
    }
}

func convertPhoneNumber(rawNumber: String) -> String {
    let regex = try! PhoneNumberConverter(pattern: "([0-9]{3})([0-9]{1,3})([0-9]{0,4})")
    return regex.stringByReplacingMatches(
        in: rawNumber,
        options: .reportCompletion,
        range: NSRange(location: 0, length: rawNumber.characters.count),
        withTemplate: "($1) $2-$3"
    )
}
print(convertPhoneNumber(rawNumber: "5125")) //->(512) 5
print(convertPhoneNumber(rawNumber: "512512345")) //->(512) 512-345

答案 1 :(得分:2)

在没有花哨的情况下,我在三元条件运算符中使用了替代模板的方法:

let rawNumber = "512512345"

let regex = try NSRegularExpression(pattern: "([0-9]{3})([0-9]{1,3})([0-9]{0,4})")
regex.stringByReplacingMatches(
    in: rawNumber,
    options: .reportCompletion,
    range: NSRange(location: 0, length: rawNumber.characters.count),
    withTemplate: "\(rawNumber.count > 6 ? "($1) $2-$3" : "($1) $2")"
)

rawNumber = "5125"的结果为"(512) 5"rawNumber = "512512345""(512) 512-345"

编辑:Swift 4.2 (并将结果放入常量)

    let rawNumber = "512512345"

    if let formattedString =
        try? NSRegularExpression(pattern: "([0-9]{3})([0-9]{1,3})([0-9]{0,4})", options: []).stringByReplacingMatches(in: rawNumber, options: .reportCompletion, range: NSRange(location: 0, length: rawNumber.count), withTemplate: "\(rawNumber.count > 6 ? "($1) $2-$3" : "($1) $2")") {
        print(formattedString)
    }

答案 2 :(得分:0)

看起来没有办法做到这一点,因为除了捕获组之外,所有template字符串都被解释为文字字符。

https://developer.apple.com/reference/foundation/nsregularexpression

enter image description here

答案 3 :(得分:0)

而不是stringByReplacingMatches,请使用matchesInString。这将为您提供匹配列表(应该只有一个),它本身包含每个捕获组的范围列表。

然后,您可以检查哪个捕获组确实匹配,并从那里使用一个模板或另一个模板。