【问题标题】:iOS NSRegularExpression with conditional piece of template带有条件模板的 iOS NSRegularExpression
【发布时间】:2017-02-21 16:15:28
【问题描述】:

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

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

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-,因为除非找到第三个捕获组,否则我不希望显示-

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

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

【问题讨论】:

    标签: ios regex swift nsregularexpression


    【解决方案1】:

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

    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】:

      您可以编写自己的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
      

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            猜你喜欢
            • 2021-03-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-04-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多