【问题标题】:How to group search regular expressions using swift如何使用 swift 对搜索正则表达式进行分组
【发布时间】:2015-01-19 23:04:59
【问题描述】:

在正则表达式中,您可以对不同的匹配进行分组以轻松“模式匹配”给定的匹配。

while match != nil {
  match = source.rangeOfString(regex, options: .RegularExpressionSearch)
  if let m = match {
    result.append(source.substringWithRange(m)
      source.replaceRange(m, with: "") 
  }
}

上面的作品 find 找到匹配的范围,但它不能告诉我组。例如,如果我搜索封装在“”中的单词,我想匹配一个“单词”,但快速只获取单词

是否有可能在swift中这样做?

【问题讨论】:

    标签: regex swift


    【解决方案1】:

    现在 Swift 的正则表达式相当难看——让我们希望尽快获得更多原生支持!你想要的NSRegularExpression 上的方法是matchesInString。使用方法如下:

    let string = "This is my \"string\" of \"words\"."
    let re = NSRegularExpression(pattern: "\"(.+?)\"", options: nil, error: nil)!
    let matches = re.matchesInString(string, options: nil, range: NSRange(location: 0, length: string.utf16Count))
    
    println("number of matches: \(matches.count)")
    
    for match in matches as [NSTextCheckingResult] {
        // range at index 0: full match
        // range at index 1: first capture group
        let substring = (string as NSString).substringWithRange(match.rangeAtIndex(1))
        println(substring)
    }
    

    输出:

    number of matches: 2
    string
    words
    

    【讨论】:

    • 谢谢。现在必须这样做。我希望有一个更原生的解决方案,但是,Swift 是并且将是“基于扩展的”,所以我认为它不会在不久的将来实现,除了第 3 部分开发人员
    【解决方案2】:

    如果你想收集匹配的字符串,你可以使用它。 (我的答案来自 Nate Cooks 非常有帮助的答案。)

    为 Swift 2.1 更新

    extension String {
        func regexMatches(pattern: String) -> Array<String> {
            let re: NSRegularExpression
            do {
                re = try NSRegularExpression(pattern: pattern, options: [])
            } catch {
                return []
            }
    
            let matches = re.matchesInString(self, options: [], range: NSRange(location: 0, length: self.utf16.count))
            var collectMatches: Array<String> = []
            for match in matches {
                // range at index 0: full match
                // range at index 1: first capture group
                let substring = (self as NSString).substringWithRange(match.rangeAtIndex(1))
                collectMatches.append(substring)
            }
            return collectMatches
        }
    }
    

    为 Swift 3.0 更新

    extension String {
    func regexMatches(pattern: String) -> Array<String> {
        let re: NSRegularExpression
        do {
            re = try NSRegularExpression(pattern: pattern, options: [])
        } catch {
            return []
        }
    
        let matches = re.matches(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count))
        var collectMatches: Array<String> = []
        for match in matches {
            // range at index 0: full match
            // range at index 1: first capture group
            let substring = (self as NSString).substring(with: match.rangeAt(1))
            collectMatches.append(substring)
        }
        return collectMatches
    }}
    

    【讨论】:

    • 这太好了,非常感谢。但以下内容有问题:"This is my \"string\" of \"words\".".regexMatches("(my )|(of )\"(.+?)\"")。它找到的两个范围是:["(8,3)", "(9223372036854775807,0)"]
    【解决方案3】:

    这些家伙怎么样,添加为字符串的扩展? )) 所有匹配项,所有组 ) self = String 如果您想添加不作为扩展名,则添加 String 参数并将所有 self 替换为您的参数:)

     func matchesForRegexInTextAll(regex: String!) -> [[String]] {
    
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = self as NSString
    
            var resultsFinal = [[String]]()
    
            let results = regex.matchesInString(self,
                options: [], range: NSMakeRange(0, nsString.length))
    
            for result in results {
                var internalString = [String]()
                for var i = 0; i < result.numberOfRanges; ++i{
                    internalString.append(nsString.substringWithRange(result.rangeAtIndex(i)))
                }
                resultsFinal.append(internalString)
            }
    
            return resultsFinal
        } catch let error as NSError {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }
    

    【讨论】:

      【解决方案4】:

      提供的所有答案都很好,但我仍将提供用 Swift 2.2 编写的 my String 扩展。

      注意的区别:

      • 只使用第一个匹配项
      • 支持多个捕获组
      • 更准确的函数名称(它是捕获组,不匹配)

      .

      extension String {
          func capturedGroups(withRegex pattern: String) -> [String]? {
              var regex: NSRegularExpression
              do {
                  regex = try NSRegularExpression(pattern: pattern, options: [])
              } catch {
                  return nil
              }
      
              let matches = regex.matchesInString(self, options: [], range: NSRange(location:0, length: self.characters.count))
      
              guard let match = matches.first else { return nil }
      
              // Note: Index 1 is 1st capture group, 2 is 2nd, ..., while index 0 is full match which we don't use
              let lastRangeIndex = match.numberOfRanges - 1
              guard lastRangeIndex >= 1 else { return nil }
      
              var results = [String]()
      
              for i in 1...lastRangeIndex {
                  let capturedGroupIndex = match.rangeAtIndex(i)
                  let matchedString = (self as NSString).substringWithRange(capturedGroupIndex)
                  results.append(matchedString)
              }
      
              return results
          }
      }
      

      使用方法:

      // Will match "bcde"
      "abcdefg".capturedGroups(withRegex: "a(.*)f")
      

      【讨论】:

      • 我投了赞成票,但最后这段代码不可靠。使用模式 "([NSEW]|\\-?)\\s*([0-9]{1,3}(\\.[0-9]+)?)(,\\s*|\ \s+)([NSEW]|\\-?)\\s*([0-9]{1,3}(\\.[0-9]+)?)" 和字符串 "1 2" 它崩溃(capturedGroupIndex.location 对于最后一场比赛来说太高了)。
      • 添加检查到 captureGroupIndex.location != NSNotFound 并返回一个空字符串解决了这个问题。请考虑为其他人更新您的答案。
      【解决方案5】:

      为 Swift 4 更新

      /**
       String extension that extract the captured groups with a regex pattern
      
       - parameter pattern: regex pattern
       - Returns: captured groups
       */
      public func capturedGroups(withRegex pattern: String) -> [String] {
          var results = [String]()
      
          var regex: NSRegularExpression
          do {
              regex = try NSRegularExpression(pattern: pattern, options: [])
          } catch {
              return results
          }
          let matches = regex.matches(in: self, options: [], range: NSRange(location:0, length: self.count))
      
          guard let match = matches.first else { return results }
      
          let lastRangeIndex = match.numberOfRanges - 1
          guard lastRangeIndex >= 1 else { return results }
      
          for i in 1...lastRangeIndex {
              let capturedGroupIndex = match.range(at: i)
              let matchedString = (self as NSString).substring(with: capturedGroupIndex)
              results.append(matchedString)
          }
      
          return results
      }
      

      使用方法:

      // Will match "bcde"
      "abcdefg".capturedGroups(withRegex: "a(.*)f")
      

      github 上的要点:https://gist.github.com/unshapedesign/1b95f78d7f74241f706f346aed5384ff

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-09
        • 1970-01-01
        • 1970-01-01
        • 2019-02-18
        • 1970-01-01
        • 2017-06-26
        相关资源
        最近更新 更多