2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

名前付きで正規表現の結果をキャプチャする

Last updated at Posted at 2016-03-08

こんな感じで正規表現の結果を参照したかったので作ってみました

let target = "^/users/(?<user_id>[0-9]+)/items/(?<item_id>[0-9]+)$"
let regex = try! NameCaptureRegex(pattern: target)

if case let .Match(parameter) = regex.match("/users/1/items/100") {
    print(parameter["user_id"]) // "1"
    print(parameter["item_id"]) // "100"
}

実装

public final class NameCaptureRegex {
    
    public enum Result {
        case Match([String: String])
        case None
    }
    
    private var _regex: NSRegularExpression!
    private var _capturedKeys: [String] = []
    
    public init(pattern: String) throws {
        
        let regex = try NSRegularExpression(pattern: "\\(\\?<([a-zA-Z_][0-9a-zA-Z_]+)>(.+?)\\)", options: [])
        
        let formattedPattern = regex.stringByReplacingMatchesInString(
            pattern, options: [], range: NSMakeRange(0, pattern.utf16.count), withTemplate: "($2)"
        )
        
        _capturedKeys = regex.matchesInString(pattern, options: [], range: NSMakeRange(0, pattern.utf8.count)).map {
            let range = $0.rangeAtIndex(1)
            let start = pattern.utf16.startIndex.advancedBy(range.location)
            let end = start.advancedBy(range.length)
            return String(pattern.utf16[start..<end])
        }
        
        _regex = try NSRegularExpression(pattern: formattedPattern, options: [])
    }
    
    public func match(target: String) -> Result {
        
        let results = _regex.matchesInString(target, options: [], range: NSMakeRange(0, target.utf16.count))
        
        if results.isEmpty {
            return .None
        }
        var dict: [String: String] = [:]
        for i in 1..<results[0].numberOfRanges {
            let range = results[0].rangeAtIndex(i)
            let start = target.utf16.startIndex.advancedBy(range.location)
            let end = start.advancedBy(range.length)
            
            dict[_capturedKeys[i-1]] = String(target.utf16[start..<end])
        }
        return .Match(dict)
    }
}

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?