BioPlayground

🧬
목록으로

정규표현식으로 서열 데이터 파싱하기

Python re 모듈로 FASTA 헤더 파싱, 서열 패턴 검색, 데이터 추출하기. 바이오 연구자 맞춤 정규표현식 가이드.

입문
|
60
|
검증 완료 (2026-06)
정규표현식regexFASTA패턴 매칭서열 파싱re 모듈
트랙 진행률0/6 (0%)

정규표현식으로 서열 데이터 파싱하기

이 토픽을 마치면

Python의 re 모듈로 텍스트에서 패턴을 검색하고, FASTA 헤더에서 정보를 추출하고, 서열 데이터를 검증할 수 있습니다.


정규표현식이 필요한 순간

FASTA 파일의 헤더를 봅시다:

text
>sp|P04637|P53_HUMAN Cellular tumor antigen p53 OS=Homo sapiens OX=9606

이 한 줄에서 "P04637" (UniProt ID)만 추출하고 싶습니다. 문자열을 split("|")로 쪼갤 수도 있지만, 헤더 형식이 파일마다 다르면 매번 다른 코드를 써야 합니다.

**정규표현식(Regular Expression, regex)**은 "패턴"으로 텍스트를 검색합니다. "파이프 기호 사이에 있는 영숫자" 같은 패턴을 정의하면, 어떤 형식의 헤더에서든 같은 코드로 추출할 수 있습니다.

실험에서 비유하면 — 특정 항체가 특정 에피토프(패턴)에 결합하듯, 정규표현식은 텍스트에서 특정 패턴에 "결합"합니다.

Python re 모듈 기초

python
import re
text = "EGFR expression: 12.5 ng/mL"
match = re.search(r"\d+\.\d+", text)
if match:
value = float(match.group())
print(f"수치: {value}")
assert value == 12.5

re.search(패턴, 텍스트) — 텍스트에서 패턴과 일치하는 첫 번째 부분을 찾습니다.

핵심 패턴 문자

패턴의미예시매칭 결과
\d숫자 한 개\d\d"42"
\d+숫자 하나 이상\d+"123", "4"
\w영숫자 + 밑줄\w+"gene_1"
.아무 문자 하나a.b"a1b", "a-b"
*앞 패턴 0회 이상ab*c"ac", "abc", "abbc"
+앞 패턴 1회 이상ab+c"abc", "abbc" (ac는 X)
?앞 패턴 0 또는 1회colou?r"color", "colour"
[ABC]A, B, C 중 하나[ATGC]+"ATGCGTA"
^줄의 시작^>FASTA 헤더 줄
|또는 (OR)cat|dog"cat" 또는 "dog"

패턴 앞에 r을 붙이면 raw string이 됩니다 (r"\d+"). 역슬래시(\)가 Python 문자열 이스케이프와 충돌하는 것을 방지합니다. 정규표현식에서는 항상 r"..." 형태를 쓰세요.

실전: FASTA 헤더 파싱

python
import re
header = ">sp|P04637|P53_HUMAN Cellular tumor antigen p53 OS=Homo sapiens OX=9606"
uniprot_id = re.search(r"\|(\w+)\|", header)
if uniprot_id:
print(f"UniProt ID: {uniprot_id.group(1)}")
organism = re.search(r"OS=(.+?) OX=", header)
if organism:
print(f"Organism: {organism.group(1)}")

출력:

text
UniProt ID: P04637
Organism: Homo sapiens

() — 괄호로 감싼 부분이 캡처 그룹입니다. group(1)로 괄호 안의 내용만 추출합니다.

.+??를 붙이면 최소 매칭(lazy match)입니다. 가능한 한 적게 매칭합니다. ? 없이 .+만 쓰면 가능한 한 많이 매칭해서(greedy) 의도와 다른 결과가 나올 수 있습니다.

실전: DNA 서열에서 모티프 찾기

특정 제한효소 인식 부위를 서열에서 모두 찾고 싶을 때:

python
import re
sequence = "ATCGAATTCGCGAATTCTTGAATTCAA"
# EcoRI 인식 부위: GAATTC
sites = [m.start() for m in re.finditer(r"GAATTC", sequence)]
print(f"EcoRI 절단 위치: {sites}")
print(f"절단 부위 수: {len(sites)}")
assert len(sites) == 3
assert sites == [4, 13, 20]

re.finditer()는 모든 매칭을 반복적으로 찾아줍니다. re.search()는 첫 번째만 찾지만, finditer()는 전부 찾습니다.

실전: 서열 검증

입력된 서열이 유효한 DNA 서열인지 검증합니다:

python
import re
def is_valid_dna(seq: str) -> bool:
return bool(re.fullmatch(r"[ATGCatgc]+", seq))
print(is_valid_dna("ATGCGATCGA"))
print(is_valid_dna("ATGXYZ"))
print(is_valid_dna(""))
assert is_valid_dna("ATGCGATCGA") == True
assert is_valid_dna("ATGXYZ") == False
assert is_valid_dna("") == False

re.fullmatch() — 문자열 전체가 패턴과 일치해야 합니다. re.search()와 달리 부분 매칭은 허용하지 않습니다.

re 모듈 주요 함수 정리

함수용도반환값
re.search(패턴, 텍스트)첫 번째 매칭 찾기Match 객체 또는 None
re.findall(패턴, 텍스트)모든 매칭을 리스트로문자열 리스트
re.finditer(패턴, 텍스트)모든 매칭을 순회Match 객체 iterator
re.sub(패턴, 대체, 텍스트)패턴을 다른 문자열로 교체새 문자열
re.fullmatch(패턴, 텍스트)전체가 패턴과 일치하는지Match 객체 또는 None

직접 해보기 (Faded Example)

아래 빈칸을 채워 FASTA 헤더에서 유전자 이름을 추출하는 코드를 완성하세요.

빈칸 채우기python
import
header = ">gene_BRCA1 | Homo sapiens | chromosome 17"
match = re.(r"gene_(\w+)", header)
if match:
gene_name = match.group()
print(f"유전자: {gene_name}")

흔한 에러 & 해결법

Q: 패턴이 맞는 것 같은데 None이 반환됩니다

대소문자를 확인하세요. re.search(r"gaattc", "GAATTC")는 매칭되지 않습니다. 대소문자를 무시하려면 re.IGNORECASE 플래그를 추가하세요: re.search(r"gaattc", "GAATTC", re.IGNORECASE)

Q: \d가 동작하지 않습니다

문자열 앞에 r을 붙였는지 확인하세요. "\d"는 Python이 \d를 이스케이프 시퀀스로 해석하려 합니다. r"\d"로 쓰면 raw string으로 처리되어 정규표현식 엔진에 그대로 전달됩니다.

Q: 정규표현식이 너무 복잡합니다. 꼭 써야 하나요?

간단한 경우에는 in, startswith(), split() 등 문자열 메서드가 더 읽기 쉽습니다. 정규표현식은 패턴이 복잡하거나 여러 형식을 한꺼번에 처리해야 할 때 힘을 발합니다. "CTRL+F로 안 되는 검색"이 필요하면 정규표현식을 쓰세요.