2024. 7. 7. 01:18ㆍDevelopers 공간 [Shorts]/Vision & Audio
<분류>
A. 수단
- OS/Platform/Tool : Linux, Kubernetes(k8s), Docker, AWS
- Package Manager : node.js, yarn, brew,
- Compiler/Transpillar : React, Nvcc, gcc/g++, Babel, Flutter
- Module Bundler : React, Webpack, Parcel
B. 언어
- C/C++, python, Javacsript, Typescript, Go-Lang, CUDA, Dart, HTML/CSS
C. 라이브러리 및 프레임워크 및 SDK
- OpenCV, OpenCL, FastAPI, PyTorch, Tensorflow, Nsight
1. What? (현상)
정규표현식(Regular Expression)은 프로그래밍 언어에서 문자열의 검색과 치환을 위해 사용하는 형식언어 입니다.
정규표현식은 " ^ + ? ( [ " 와 같이 원래 의미가 아닌 다른 뜻을 가진 Meta Characters들로 이루어져 있어 이들을 이해하고 사용하는 것이 중요합니다.
정규표현식을 이용한 변환은 웹페이지(https://regex101.com/r/rMbYHz/4)에서 확인할 수도 있고, 직접 코드에서 re 패키지 활용할 수도 있습니다.
이에 대한 사용 예시를 여러가지 살펴보면서 이해해보려고 하는데, 이번 글에서는 문자 클래스 []를 활용하는 예시를 주로 보이겠습니다.
2. Why? (원인)
- X
3. How? (해결책)
시작하기에 앞서 re 패키지의 기본적인 특징에 대해 설명하겠습니다.
아래와 같은 코드 중 Version1이 Version2과 다른 것은 compile을 활용해 미리 패턴을 지정해 놓은 것입니다.
import re
# Version1
p = re.compile(r"[ㄱ-ㅣ가-힣]")
r = p.match(input)
if not r is None:
replaced = p.sub("", input)
# Version2
r = re.search(r"[ㄱ-ㅣ가-힣]", input)
if not r is None:
replaced = re.sub(r"[ㄱ-ㅣ가-힣]", "", input)
이렇게 패턴을 검색할 때는 아래와 같이 세가지가 있습니다.
- match() : 문자열의 처음부터 매치되는지 조사
- search() : 문자열의 전체 중 일치되는 것이 있는지 조사
- findall() : 문자열의 전체 중 일치되는 것이 있으면 리스트로 return
- finditer() : 문자열의 전체 중 일치되는 것이 있으면 iter로 return
이제 정규표현식을 표현하겠습니다. 정규표현식을 표현할 때 특징은 아래와 같습니다.
Pattern | 설명 | 예제 |
r"" | r을 붙여주는 경우는 backslash를 escape가 아닌 일반적인 문자로 인식하기 위해 사용합니다 | re.compile("\n") : new line re.compile(r"\n"):두개의 character |
"^ $" | 문장의 시작^과 문장의 끝$을 의미합니다. | re.compile("^abc$") |
\ | 이스케이프(Escape)라 하며 해당 특수시퀀스를 알리기 위해 사용합니다. | \d : 숫자 [0-9] \D : 숫자아님 [^0-9] \w : 모든 문자+숫자 [a-zA-Z0-9_] \W : 모든 문자+숫자 아닌것 [^a-zA-Z0-9_] \s : white space [ \t\n\r\f\v] |
[] | 문자클래스로, 아래에서 설명하겠습니다. | |
. | dot 문자로, \n을 제외한 모든 문자를 의미합니다. | re.compile("a.z") : abz, a0z... 등등 |
문자* | 해당 문자가 0~무제한 반복 가능합니다. | re.compile("ab*") : a, ab, abb ... |
문자+ | 해당 문자가 1~무제한 반복 가능합니다. | re.compile("ab+"): ab, abb ... |
{} | 반복횟수를 제한할 때 사용합니다. | re.compile("ab{2}"): abb re.compile("ab{2,3}"): abb, abbb |
? | 0번~1번 반복하는 것으로, {0,1}과 같다. | re.compile("ab?"): a, ab |
그럼 이제 문자클래스를 살펴보겠습니다. 문자 클래스 []는 [ 와 ] 사이에 문자들을 표현해 일치하는지 확인할 수 있습니다.
Pattern | 설명 | 예제 |
[문자들] | 해당 문자들 중에 하나 | [0-5][0-9] : 00에서 59까지의 두자리 숫자 [a-z] : 모든 소문자 ASCII문자 [0-9A-Fa-f] : 모든 16진수 [a-zA-Z] : 영어 [ㄱ-ㅣ가-힣] : 한글 [0-9] : 숫자 |
[^문자들] | 해당 문자들이 아닌 문자들 중에 하나 | [^5] : 5를 제외한 모든 문자 |
이정도로 살펴보고, 예시를 통해 살펴보겠습니다.
Case0. 한글 찾아 없애기
앞에서 살펴봤었죠? 한글을 찾아 다 없애는 방법입니다.
한글을 normalize로 unicode로 확실히 만들어준 뒤 진행했으며, re.sub(pattern, target, text) 메서드를 활용하면 찾은 정규표현식의 문자열을 치환하기 위해 사용할 수 있습니다.
import re
from unicodedata import normalize
input = normalize('NFC', input.strip())
p = re.compile(r"[ㄱ-ㅣ가-힣]")
r= p.search(input)
if not r is None:
replaced = p.sub("", input)
Case1. 시작할 때의 특정 패턴 찾아 고치기
시작할 때 패턴을 찾는 경우, 영어 또는 whitespace 가 아닌 부분을 없애주는 방법입니다.
p = re.compile("한글 [0-9][0-9] ")
p1 = re.compile("한글 [0-9][0-9]M [0-9][0-9] ")
r = p.match(input)
r1= p1.match(input)
if not r is None or not r1 is None:
replaced = re.sub(r"[^a-zA-Z\s]","", input).strip()
p = re.compile(r"^[ABC][0-9][0-9][0-9] ")
r = p.match(input)
if not r is None:
value1 = input.split(" ")[0].strip()
value2 = p.sub("", input).strip()
Case3. 시작과 끝의 패턴 찾아 고치기1
시작할 때 뿐 아니라 끝날때의 패턴도 찾아 고치는 방법입니다. 조금 자세히 보겠습니다.
- ^ : string의 시작
- [0-9]+ : 1개이상의 숫자가 연속되고
- _ : 언더바가 존재하며
- [a-zA-Z ]* : white space 혹은 영어가 존재하는 string을 지난후에
- _ : 언더바가 존재하며
- [0-9]+ : 1개 이상의 숫자가 연속되고
- $ : string의 끝
p = re.compile(r"^[0-9]+_[a-zA-Z ]*_[0-9]+$")
r = p.match(input)
if not r is None :
replaced = input.split("_")[1].strip()
Case4. 시작과 끝의 패턴 찾아 고치기2
다른 경우를 살펴보겠습니다. 가운데 "언더바를 제외한 문자"를 명시해서 언더바를 이용해 구분할 수 있게 해주었습니다.
- ^ : string의 시작
- [0-9]+ : 1개이상의 숫자가 연속되고
- _ : 언더바가 존재하며
- [^_]* : 언더바를 제외한 어떤 문자든 반복
- _ : 언더바가 존재하며
- [0-9]+ : 1개 이상의 숫자가 연속되고
- _ : 언더바가 존재하며
- ABC: ABC라는 문자가 존재하며
- $ : string의 끝
p = re.compile(r"^[0-9]+_[^_]*_[0-9]+_ABC$")
r = p.match(input)
if not r is None :
replaced = input.split("_")[1].strip()
Case5. 시작과 끝의 패턴 찾아 고치기3
계속 해서 다른 패턴을 보겠습니다.아래는 . 과 white space가 섞여있습니다.
- ^ : string의 시작
- [0-9]+ : 1개이상의 숫자가 연속되고
- \. : dot 이 존재하며
- [a-zA-Z ]* : white space 혹은 영어가 존재하는 string을 지난후에
- : white space 가 존재하며
- [0-9_]+ : 1개 이상의 숫자 혹은 언더바가 연속되고
- $ : string의 끝
p = re.compile(r"^[0-9]+\.[a-zA-Z ]* [0-9_]+$")
r = p.match(input)
if not r is None :
replaced = " ".join(input.split(".")[1].split("_")[0].split(" ")[:-1]).strip()
Case6.시작과 끝의 패턴 찾아 고치기4
마지막으로 복습겸 다시 보겠습니다.
- ^ : string의 시작
- [0-9][0-9] : 2개의 숫자
- _ : 언더바가 존재하며
- [^_]* : 언더바가 아닌 어떤 문자든 반복
- _ : 언더바가 존재하며
- [0-9_\,]+ : 1개 이상의 숫자 혹은 언더바 혹은 콤마가 연속되고
- ABC : ABC라는 문자가 존재하고
- $ : string의 끝
p = re.compile(r"^[0-9][0-9]_[^_]*_[0-9_\,]* ABC$")
r = p.match(input)
if not r is None :
replaced = input.split("_")[1].strip()
'Developers 공간 [Shorts] > Vision & Audio' 카테고리의 다른 글
[Audio] Python에서 Audio 불러오기 (0) | 2024.07.15 |
---|---|
[Audio] Python에서 MIDI 파일 다루기 (0) | 2024.07.15 |
[NLP] Faiss와 CLIP을 이용한 간단한 Text Retrieval 구현하기 (0) | 2024.06.06 |
[Generative] Diffusion 모델 원하는 위치에 받기 (0) | 2024.03.28 |
[Audio] ASR에서 CER, WER 구현 및 측정해보기 (0) | 2024.02.09 |