적당한 고통은 희열이다

- 댄 브라운 '다빈치 코드' 중에서

Algorithm/참고

Swift 정규식 NSRegularExpression

hongssup_ 2022. 1. 4. 17:08
반응형

WWDC 2022 what's new in swift 에서 새로운 Swift Regex 를 발표했다.

import RegexBuilder 하면

정규식 리터럴 대안으로, 알아보기 힘든 복잡한 정규식을 단어로 작성해서 더 이해하기 편하고 읽기 쉬운 SwiftUI 스타일 언어를 제공한다고 한다. 

 

참고 : https://developer.apple.com/videos/play/wwdc2022/110354/


<기존 정규식 사용법>

 

OCR 로 영수증 인식해서 값을 추출해야하는데

이게 과연 앱개발의 영역인가.. 이거는 머신러닝으로 해야하는거 아닌가 싶지만 

우선 영수증에 있는 날짜와 금액 등을 불러오기 위해 정규표현식에 대해 먼저 알아보았다.

 

정규표현식

: String에서 원하는 패턴이나 문자열을 추출할 때 사용하는 방법

 

Swift는 언어 자체에서 정규식을 지원하지는 않고, Foundation의 NSRegularExpression 클래스를 이용한다. 

 

정규식 타입 만들기

^ : 시작

$ : 종료

[] : 괄호 안에 있는 문자 중 임의의 한 문자

{} : 괄호 안의 임의의 문자 갯수. {0, } 는 0개 이상, {2,4} 는 2 이상 4 이하.

문자 뒤에 ? : optional. 있을 수도 없을 수도 있는 값

let pattern = "^[A-Za-z0-9]{0,}$"
// A-z a-z 0-9 에 속하는 문자열인지 검사

 

 

날짜 정규식

yyyy-MM-dd  yyyy/MM/dd  yyyy.MM.dd 이런 다양한 형식을 지원해주기 위해 [-/.]를 넣어주었다. 

그냥 숫자네자리-숫자 두자리-숫자두자리 로 추출할거면 간단하게 위의 방식도 괜찮고

진짜 완전 날짜형식만! 하면 정확하게는 아래의 패턴으로 사용하면 될 듯 하다. 

let datePattern: String = "(?<year>[0-9]{4})[-/.](?<month>[0-9]{2})[-/.](?<date>[0-9]{2})"
let datePattern: String = "(?<year>(19|20)[0-9]{2})[-/.](?<month>(0[1-9]|1[0-2]))[-/.](?<date>(0[1-9]|1[0-9]|2[0-9]|3[0-1]))"
let str = "[승인 일시] 2021-11-29 18:07:53"
let datePattern: String = "(?<year>[0-9]{2,4})[-/.](?<month>[0-9]{2})[-/.](?<date>[0-9]{2})"
let regex = try? NSRegularExpression(pattern: datePattern, options: [])
if let result = regex?.matches(in: str, options: [], range: NSRange(location: 0, length: str.count)) {
    let rexStrings = result.map { (element) -> String in
        let yearRange = Range(element.range(withName: "year"), in: str)!
        let monthRange = Range(element.range(withName: "month"), in: str)!
        let dateRange = Range(element.range(withName: "date"), in: str)!
        return "\(str[yearRange])년 \(str[monthRange])월 \(str[dateRange])일"
    }
    print(rexStrings) //["2021년 11월 29일"]
}

 

가격/금액 정규식

let priceStr = "수량 3 단가 7,000 금액 21,000 합계: 3,215,000"
let pricePattern: String = "([0-9]{0,3}),?([0-9]{0,3}),([0-9]{3})"

let regex = try? NSRegularExpression(pattern: pricePattern, options: [])
if let result = regex?.matches(in: priceStr, options: [], range: NSRange(location: 0, length: priceStr.count)) {
    let priceStrings = result.map { (element) -> String in
        let range = Range(element.range, in:priceStr)!
        return String(priceStr[range])
    }
    print(priceStrings) //["7,000", "21,000", "3,215,000"]
}

 

핸드폰 번호 정규식

^01([0-9])([0-9]{3,4})([0-9]{4})$
^010-?([0-9]{4})-?([0-9]{4})

 

문자열 일부가 일치하는지 확인하는 법 (가장 첫번째로 일치하는 부분만)

// string: 정규식과 비교할 문자열
// regex: 정규식 문자열

string.range(of: regex, options: .regularExpression)

 

문자열에 숫자가 포함되어 있는지 확인하는 법

728x90
반응형

'Algorithm > 참고' 카테고리의 다른 글

[Swift] 2진수 변환 radix  (0) 2022.02.09
[Swift] reversed()  (1) 2022.01.16
[Swift] String 문자열 다루기  (2) 2022.01.10
[Swift] Array 배열 관련 함수들  (0) 2022.01.06
[Swift iOS] Dictionary 사용법 + dictionaries inside array  (0) 2021.09.10