본문 바로가기
C.W.K.
Stream
Lesson 06 of 12 · published

따옴표로 감싼 필드가 있는 CSV

~10 min · csv, parsing, quoting

Level 0패턴 호기심
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

실제 CSV에는 예외가 많아

str.split(',')는 필드 안에 쉼표가 없는 단순한 데이터에서만 안전해. 실제 CSV에는 따옴표로 감싼 필드 안의 쉼표와 줄바꿈, 두 개의 따옴표로 나타내는 이스케이프, 도구마다 다른 방언 설정이 들어갈 수 있어.

파일을 제대로 읽고 쓸 때는 Python의 csv나 JavaScript의 Papa Parse처럼 CSV 방언을 아는 라이브러리를 사용해.

제약이 분명한 한 줄을 살펴볼 때

입력이 한 줄이고 필드 안에 이스케이프된 따옴표나 줄바꿈이 없다고 보장할 수 있다면 다음 패턴으로 기본 구조를 실험할 수 있어. 표준 CSV 전체를 구현한 패턴은 아니야.

(?:"([^"]*)"|([^,]*))(?:,|$)

각 매칭은 따옴표 안의 값 또는 쉼표가 없는 값을 캡처한 뒤 쉼표나 줄 끝에서 멈춰.

finditer로 매칭을 순회하기

두 캡처 그룹 중 값이 있는 쪽을 선택하면 각 필드를 얻을 수 있어. 다만 이 패턴은 문자열 끝에서 너비 0인 가짜 빈 필드를 만들 수 있으므로 반복 위치와 종료 조건을 별도로 검사해야 해. 아래 예시의 마지막 빈 문자열이 바로 그 한계를 보여 줘.

여러 줄 필드는 라이브러리에 맡겨

따옴표로 감싼 필드 안에 줄바꿈까지 허용하면 줄 단위 정규식으로는 레코드의 끝을 안전하게 판단하기 어려워. 이스케이프와 방언까지 정확히 처리해야 하는 실서비스 코드에서는 csv 모듈을 사용해.

Code

따옴표가 있는 한 줄 CSV·python
import re

CSV_LINE = re.compile(r'(?:"([^"]*)"|([^,]*))(?:,|$)')

def parse_csv_line(line):
    fields = []
    for m in CSV_LINE.finditer(line):
        quoted, bare = m.groups()
        fields.append(quoted if quoted is not None else bare)
        if not m.group():
            break
    return fields

parse_csv_line('Pippa,"3, going on 30",warm')
# ['Pippa', '3, going on 30', 'warm', '']

# 진짜 CSV 처리엔 라이브러리
import csv
import io

lines = '''name,age,mood
Pippa,"3, going on 30",warm
"Wankyu, C.W.K.",58,curious'''

for row in csv.DictReader(io.StringIO(lines)):
    print(row)
# {'name': 'Pippa', 'age': '3, going on 30', 'mood': 'warm'}
# {'name': 'Wankyu, C.W.K.', 'age': '58', 'mood': 'curious'}

External links

Exercise

스프레드시트에서 내보낸 파일처럼 실제 CSV를 하나 골라 한 줄을 위 정규식과 csv.reader로 각각 읽어 봐. 두 결과가 처음 달라지는 줄을 찾아 어떤 CSV 규칙이 차이를 만들었는지 설명해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.