꿈돌이랜드

[Swift] Swift5.7 이후의 Regex 본문

Programming/Swift

[Swift] Swift5.7 이후의 Regex

loinsir 2023. 8. 30. 17:02
반응형

Swift5.7 Regex

Swift 5.7 이후, Swift 언어에서 정규 표현식 사용 방법이 업데이트 되었습니다. 이를 정리해보도록 하겠습니다.

Swift 5.7 이전, 정규표현식을 사용하려면 다음의 것들을 사용했어야 했습니다.

  1. NSRegularExpression
  1. NSString의 메서드 range(), replacingOccurrences() …

다음은 예시 코드 입니다.

  1. 문자열 일부 일치 확인
import Foundation

let str = "abcd1234"
let pattern = "[0-9]*"
if let range = str.range(of: pattern, options: .regularExpression) {
  print(str[range]) // 가장 앞 부분 부터 일치하는 부분을 반환
}
 
  1. 일치하는 모든 범위 확인
import Foundation

let str = "abcd1234"
let pattern = "[0-9]*"

do {
  let regex = try NSRegularExpression(pattern: pattern, options: [])
  let result = regex.matches(in: str, options: [], range: NSRange(location: 0, length: str.count))
	
  result.forEach { 
    let range = Range($0.range, in: str)!
    print(String(str[range])
  }
} catch {
  print(error.localizedDescription)
}

이제 Swift 5.7 이후 다음과 같은 것들이 가능해졌습니다.

새로운 Regex 타입의 추가

기존 방식과 비슷하게 문자열로 Regex객체를 생성하여 다음과 같은 사용이 가능합니다.

do {
  let regex = try Regex("[a-z][1-4]")
  print(regex.ranges(of: str))
} catch {
  print("Failed to create regex")
}

혹은 정규식 리터럴로 생성하여 try - catch 구문 없이 생성할 수 있습니다.

let keyAndValuePattern = /(.+?): (.+)/

이제 Regex 타입을 string이나 substring의 contains 메서드나, firstMatch(of:), matches(of:) 등의 메서드를 통해 사용할 수 있습니다.

let setting = "color: 161 103 230"
if setting.contains(simpleDigits) {
    print("'\(setting)' contains some digits.")
}
// Prints "'color: 161 103 230' contains some digits."

캡처된 값을 얻고 싶으면, Regex.Match 타입의 output 프로퍼티를 통해 얻을 수 있습니다.

if let match = setting.firstMatch(of: keyAndValue) {
    print("Key: \(match.1)")
    print("Value: \(match.2)")
}
// Key: color
// Value: 161 103 230

RegexBuilder를 통한 Regex 생성

RegexBuilder를 사용하여 Regex를 선언적으로 생성할 수 있습니다. 이를 사용하기 위해서는 RegexBuilder를 import 해줘야 합니다.

import Foundation
import RegexBuilder

let word = OneOrMore(.word)
let emailPattern = Regex {
    Capture {
        ZeroOrMore {
            word
            "."
        }
        word
    }
    "@"
    Capture {
        word
        OneOrMore {
            "."
            word
        }
    }
}


let text = "My email is my.name@example.com."
if let match = text.firstMatch(of: emailPattern) {
    let (wholeMatch, name, domain) = match.output
    // wholeMatch is "my.name@example.com"
    // name is "my.name"
    // domain is "example.com"
}

하위 구성요소

RegexBuilder에서 사용할 수 있는 하위 구성요소들을 다음과 같습니다.

  • CharacterClass
    • 개별 문자, 문자 그룹, 일부와 일치하는 문자 세트 등을 나타냅니다.
  • Anchor
    • 입력 문자열의 특정 위치에서 특정 조건과 일치하는 요소 입니다. 검색 시 문자열을 소비하지 않습니다.
  • Lookahead
    • 전방탐색. 구문이 일치하는 부분 이후에서만 검색을 계속하게 하는 위치를 나타냅니다.
  • NegativeLookahead
    • 전방부정탐색. 구문이 일치하지 않는 부분 이후에서만 검색을 계속하게 하는 위치를 나타냅니다.
  • ChoiceOf
    • 일치 할 경우 정규식 구성 요소 중 정확히 하나를 선택하는 정규식 구성 요소입니다.
  • One
    • 기본 구성 요소와 정확히 일치하는 구성 요소를 나타냅니다.
  • Optionally
    • 기본 구성 요소와 0개 또는 1개 항목과 일치하는 구성 요소를 나타냅니다.
  • ZeroOrMore
    • 0개 이상의 기본 구성 요소와 일치하는 정규식 구성 요소입니다.
  • OneOrMore
    • 기본 구성 요소와 하나 이상 일치하는 정규식 구성 요소입니다.
  • Repeat
    • 기본 구성 요소의 발생 횟수와 일치하는 정규식 구성 요소입니다.
  • Local
    • 그룹을 나타내는 정규식 구성요소 입니다.
  • Capture
    • 정규식이 일치하는 부분에 접근하기 위해 일치하는 하위 문자열 또는 변환된 결과를 저장하는 정규식 구성 요소 입니다.
  • TryCapture
    • 일치하는 하위 문자열을 변환하려고 시도하는 정규식 구성 요소로, 성공 시 결과를 저장합니다.

참고: https://developer.apple.com/documentation/regexbuilder

Uploaded by N2T

반응형