Skip to content

7주차 · 문자열과 데이터 파싱

이번 주 이야기: “센서가 보내온 텍스트, 어떻게 숫자로 바꿀까?”

Section titled “이번 주 이야기: “센서가 보내온 텍스트, 어떻게 숫자로 바꿀까?””

실제 장비나 파일에서 읽어온 데이터는 대부분 문자열로 들어옵니다.

" sensor=A1, value= 42 , unit=V "
"id:001 | temp:24.8 | status:OK"

이 텍스트를 프로그램이 쓸 수 있는 숫자나 딕셔너리로 바꾸는 작업이 파싱(parsing) 입니다.

이번 주 목표는 단순합니다.

  1. 문자열 메서드 4개(strip, split, replace, join)를 익히고
  2. 정제 → 분리 → 검증 → 변환 순서를 몸에 익히며
  3. 리스트 컴프리헨션으로 반복 처리를 한 줄로 줄이기
  • 문자열 인덱싱/슬라이싱을 실수 없이 읽는다.
  • 문자열이 immutable(불변)이라는 의미를 코드로 이해한다.
  • strip, split, replace, join, find를 목적에 맞게 조합한다.
  • 텍스트를 정제 → 분리 → 검증 → 변환 순서로 처리한다.
  • 리스트 컴프리헨션 기본 형태를 읽고 작성한다.
  • C 문자열과 Python 문자열의 차이를 설명한다.

1) 문자열 기초: 인덱싱과 슬라이싱

Section titled “1) 문자열 기초: 인덱싱과 슬라이싱”

문자열은 인덱스가 있는 문자 시퀀스입니다.

text = "signal"
print(text[0]) # s (첫 글자)
print(text[-1]) # l (마지막 글자)
print(text[1:4]) # ign (1번부터 3번까지)
print(len(text)) # 6
text = "sampling"
print(text[0:4]) # samp — 0,1,2,3번 (4번 미포함)
print(text[4:]) # ling — 4번부터 끝까지
print(text[:3]) # sam — 맨앞부터 2번까지
print(text[::2]) # smln — 두 칸 간격

한 글자를 직접 바꿀 수 없습니다.

# 잘못된 방법
name = "radar"
name[0] = "R" # TypeError 발생!
# 올바른 방법
name = "R" + name[1:]
print(name) # Radar

문자열 수정은 “원본 수정”이 아니라 새 문자열 생성입니다.

raw = " temp=24.8\n"
print(raw.strip()) # temp=24.8
line = "time=12:31,temp=24.8,status=OK"
print(line.split(","))
# ['time=12:31', 'temp=24.8', 'status=OK']

두 번째 인자로 최대 분리 횟수를 지정할 수 있습니다.

line = "key:val:extra"
print(line.split(":", 1)) # ['key', 'val:extra'] — 첫 번째만 분리
msg = "temp : 24.8"
print(msg.replace(" ", "")) # temp:24.8

join() — 리스트를 하나의 문자열로

Section titled “join() — 리스트를 하나의 문자열로”
tokens = ["A", "B", "C"]
print("-".join(tokens)) # A-B-C
line = "id:001|temp:24.8"
print(line.find("|")) # 6 (없으면 -1)
print(line.find("xyz")) # -1

C와 비교: 문자열 처리 방식이 이렇게 다릅니다

Section titled “C와 비교: 문자열 처리 방식이 이렇게 다릅니다”
항목CPython기억할 점
문자열 표현char text[] = "signal";text = "signal"Python은 선언이 훨씬 짧다
길이 구하기strlen(text)len(text)함수 이름이 다르다
부분 추출루프/포인터 연산슬라이싱 text[1:4]Python은 문법으로 바로 자른다
공백 제거직접 구현/라이브러리strip()Python은 내장 메서드 사용
분리strtoksplit()Python은 원본 보존이 더 직관적
위치 탐색strstr, strchrfind()없으면 -1 반환
char text[] = "signal";
printf("%c\n", text[0]); // 첫 글자
printf("%zu\n", strlen(text)); // 길이

핵심은 Python 문자열은 슬라이싱과 메서드가 강력해서 파싱 코드가 짧아진다는 점입니다.

파싱 파이프라인
flowchart TB
  A[Raw Text] --> B["1) Clean<br/>strip(), replace()"]
  B --> C["2) Split<br/>split(',') / split(':')"]
  C --> D["3) Validate<br/>필드 수 / 키 존재 / 숫자 형태"]
  D --> E["4) Convert<br/>int(), float()"]
  E --> F["Structured Data<br/>dict / list"]

5) 리스트 컴프리헨션: 리스트를 한 줄로 만들기

Section titled “5) 리스트 컴프리헨션: 리스트를 한 줄로 만들기”

예제에서 [f.strip() for f in fields]라는 문법이 등장합니다. 이것이 리스트 컴프리헨션입니다.

[표현식 for 변수 in 반복가능한것]

위 한 줄은 아래 for 문과 정확히 같은 결과를 만듭니다.

# for 문 버전
result = []
for f in fields:
result.append(f.strip())
# 리스트 컴프리헨션 버전 (같은 동작)
result = [f.strip() for f in fields]

fields = [" A ", " B ", "C "]라고 할 때:

반복 순서ff.strip() 결과
1번째" A ""A"
2번째" B ""B"
3번째"C ""C"

최종 결과: ["A", "B", "C"]

조건을 붙일 수도 있습니다.

# 길이 4 이상인 단어만 고르기
words = ["radar", "AI", "signal", "ML"]
long_words = [w for w in words if len(w) >= 4]
print(long_words) # ['radar', 'signal']

오해 1: “split()만 하면 파싱 끝”

Section titled “오해 1: “split()만 하면 파싱 끝””
line = "id:001 | temp:24.8"
parts = line.split("|")
print(parts[1]) # ' temp:24.8' (앞 공백 포함!)

공백 때문에 키 비교가 실패합니다. strip()을 함께 써야 안전합니다.

오해 2: “숫자로 바로 바꾸는 게 빠르다”

Section titled “오해 2: “숫자로 바로 바꾸는 게 빠르다””
line = "score:NA"
score = int(line.split(":")[1]) # ValueError — 검증 없이 변환하면 바로 중단

오해 3: “인덱스 접근은 항상 가능”

Section titled “오해 3: “인덱스 접근은 항상 가능””
line = "id:001"
parts = line.split("|")
print(parts[1]) # IndexError — 필드가 1개뿐!

필드 수를 먼저 검사해야 합니다.

예제 1 · 한 줄 원시 문자열 안전 파싱 Runs in-browser with Pyodide
Ready
  1. raw는 일부러 공백이 섞인 실제 입력 상황을 흉내 냅니다.
  2. strip()으로 외곽 잡음을 먼저 제거합니다.
  3. split(”,“)로 필드 경계를 나눕니다.
  4. 리스트 컴프리헨션으로 필드별 공백을 정리해 비교 실패를 예방합니다.
  5. split(”=“)으로 키와 값을 분리하고 값을 추출합니다.
  6. isdigit() 검사로 변환 가능성을 먼저 확인합니다.
  7. 검증 통과 시에만 int()를 호출합니다.
예제 2 · 여러 줄 필드 수 검증과 continue Runs in-browser with Pyodide
Ready
  1. replace(” ”, "")로 공백을 제거한 뒤 split(”|“)로 필드를 나눕니다.
  2. continue는 “이번 반복 나머지를 건너뛰어라”는 명령입니다. 필드 수가 맞지 않으면 즉시 다음 줄로 넘어갑니다.
  3. split(”:”, 1)의 두 번째 인자 1은 maxsplit입니다. 첫 번째 콜론만 기준으로 나눠 값 안에 콜론이 있어도 안전합니다.
  4. 구조 검증이 끝난 뒤 isdigit() 패턴으로 숫자 여부를 확인한 뒤 float()로 변환합니다.
  5. 성공/실패를 동시에 출력해 데이터 품질을 확인합니다.
안티패턴실제 증상개선 습관
한 줄 체인 코딩 int(line.split(':')[1])어디서 깨졌는지 모름중간 변수로 단계 기록
매직 인덱스 남용 parts[2]IndexErrorlen(parts) 먼저 확인
검증 없는 변환ValueErrorvalidate → convert 고정
공백 무시키 미스매치strip/replace 습관화
실패 데이터 폐기디버깅 정보 손실(원문, 원인) 함께 저장

문제: 아래 코드를 실행하지 말고, 각 print의 출력값을 먼저 적어 보세요. 그 다음 콘솔에서 직접 확인하세요.

실습 문제 1 · 문자열 메서드 출력 예측 Runs in-browser with Pyodide
Ready