DaleSchool

텍스트 처리

입문25분

학습 목표

  • awk로 열 기반 텍스트를 처리할 수 있다
  • 파이프로 여러 도구를 연결해 데이터를 분석할 수 있다
  • 로그 파일 분석 시나리오를 실습할 수 있다

동작하는 코드

예제 1: grep과 wc로 기본 텍스트 분석

파이프를 활용해 단계별로 데이터를 처리합니다:

# notes.md에서 항목 수 세기
grep "항목" Documents/notes.md | wc -l

출력:

       2
# 특정 패턴을 포함하는 줄 찾기
cat Documents/notes.md | grep "^-"

출력:

- 항목 1
- 항목 2

예제 2: head와 tail 조합

# 파일의 앞부분과 뒷부분 동시에 확인
head -2 Documents/notes.md
echo "---"
tail -1 Documents/notes.md

출력:

# 메모
- 항목 1
---
- 항목 2

예제 3: 검색 결과를 파일로 저장

# grep 결과를 파일에 저장
grep "항목" Documents/notes.md > found.txt
cat found.txt

출력:

- 항목 1
- 항목 2
# wc로 여러 파일 통계 비교
wc -l Documents/hello.txt Documents/notes.md

출력:

       1 Documents/hello.txt
       3 Documents/notes.md
       4 total

직접 수정하기

awk: 열 기반 텍스트 처리

awk는 텍스트 처리에 특화된 미니 언어입니다. 특히 CSV처럼 구분자로 나뉜 데이터 처리에 강력합니다.

기본 구조:

awk '패턴 { 액션 }' 파일

예제: 기본 열 출력

# 준비: 간단한 CSV 만들기
echo "이름,점수,등급" > scores.csv
echo "홍길동,85,B" >> scores.csv
echo "김철수,92,A" >> scores.csv
echo "이영희,78,C" >> scores.csv
echo "박민수,65,D" >> scores.csv
# 첫 번째 열만 출력 (-F','는 구분자를 쉼표로 지정)
awk -F',' '{ print $1 }' scores.csv

출력:

이름
홍길동
김철수
이영희
박민수
# 이름과 점수만 출력
awk -F',' '{ print $1, $2 }' scores.csv

출력:

이름 점수
홍길동 85
김철수 92
이영희 78
박민수 65

조건 필터링

# 2열(점수)이 80 이상인 행만 출력
awk -F',' '$2 >= 80' scores.csv

출력:

이름,점수,등급
홍길동,85,B
김철수,92,A
# 헤더 제외하고 80 이상만 (NR: 줄 번호)
awk -F',' 'NR > 1 && $2 >= 80' scores.csv

출력:

홍길동,85,B
김철수,92,A

집계: BEGIN과 END

# 평균 계산
awk -F',' 'NR > 1 { sum += $2; count++ } END { print "평균:", sum/count }' scores.csv

출력:

평균: 80
# 파이프로 연결
cat scores.csv | awk -F',' 'NR > 1 { print $1, $2 }'

출력:

홍길동 85
김철수 92
이영희 78
박민수 65

"왜?" — 텍스트 처리 도구가 필요한 이유

서버 로그, CSV 데이터, 설정 파일 등 대부분의 데이터는 텍스트입니다. 이 도구들을 파이프로 조합하면 스프레드시트나 전용 프로그램 없이도 데이터를 빠르게 분석할 수 있습니다.

실전 시나리오: 로그 분석

접속 로그가 있다고 가정합니다:

2024-01-15 10:30:01 INFO 사용자 로그인: user001
2024-01-15 10:30:05 ERROR 데이터베이스 연결 실패
2024-01-15 10:30:10 INFO 파일 업로드 완료
2024-01-15 10:31:00 WARN 메모리 사용량 80% 초과
2024-01-15 10:31:05 ERROR 파일 저장 실패
# ERROR 로그만 필터
grep "ERROR" app.log

# ERROR 개수 세기
grep -c "ERROR" app.log

# 특정 시간대 로그 추출
grep "10:30" app.log | grep "ERROR"

# ERROR 메시지만 파일로 저장
grep "ERROR" app.log > errors.txt

awk 핵심 개념 정리

| 개념 | 설명 | 예시 | | ------------- | ------------ | ------------------------ | | $0 | 전체 줄 | print $0 | | $1, $2... | 각 열 | print $1, $3 | | NR | 줄 번호 | NR > 1 (헤더 제외) | | NF | 필드(열) 수 | print NF | | -F | 구분자 지정 | -F',', -F'\t' | | BEGIN | 처리 전 실행 | BEGIN { print "시작" } | | END | 처리 후 실행 | END { print sum } |

흔한 실수

실수 1: awk 열 번호는 1부터 시작

# 잘못됨: $0이 첫 번째 열이 아님
awk -F',' '{ print $0 }' file.csv   # 전체 줄 출력

# 올바름
awk -F',' '{ print $1 }' file.csv   # 첫 번째 열

실수 2: 구분자 지정 빠뜨리기

# 구분자가 쉼표인 CSV를 공백으로 처리 (틀림)
awk '{ print $1 }' scores.csv
# "이름,점수,등급"을 통째로 $1로 처리

# 올바름
awk -F',' '{ print $1 }' scores.csv

실수 3: 파이프 결과를 항상 확인하기

# 각 단계를 확인하며 파이프 구성
cat scores.csv | head -3            # 1단계 확인
cat scores.csv | head -3 | grep "8" # 2단계 확인

복잡한 파이프를 한번에 작성하기보다 단계별로 결과를 확인하며 만드세요.

심화 학습

awk 심화: 패턴 매칭과 필드 연산
# 특정 패턴의 행만 처리
awk -F',' '/A/ { print $1, "우수" }' scores.csv

# 필드 연산
awk -F',' 'NR > 1 { print $1, $2 * 1.1, "보정후" }' scores.csv

# 여러 조건
awk -F',' 'NR > 1 && $2 >= 80 && $3 == "A"' scores.csv

# 출력 형식 지정
awk -F',' 'NR > 1 { printf "%-10s %3d점\n", $1, $2 }' scores.csv
sed: 스트림 편집기

sed는 텍스트를 변환하는 도구입니다:

# 텍스트 치환 (s/원본/교체/)
echo "Hello World" | sed 's/World/Terminal/'

# 전역 치환 (g 플래그)
echo "aaa bbb aaa" | sed 's/aaa/xxx/g'

# 특정 줄 삭제
cat file.txt | sed '2d'

# 줄 번호 추가
cat file.txt | sed '='

sed는 파일 자체를 수정하지 않고 stdout으로 결과를 냅니다. 파일을 수정하려면 -i 옵션을 씁니다.

파이프 연결 시 오류 처리

파이프 중간에 명령어가 실패하면 결과가 이상해질 수 있습니다:

# set -o pipefail: 파이프 중 하나라도 실패하면 전체 실패로 처리
set -o pipefail

# 각 단계를 변수에 저장해 디버깅
result=$(cat file.txt | grep "pattern")
echo "결과: $result"
  1. echo "a,1" > data.csv, echo "b,2" >> data.csv, echo "c,3" >> data.csv로 파일을 만드세요.
  2. awk -F',' '{ print $1 }' data.csv로 첫 번째 열을 출력하세요.
  3. awk -F',' '$2 >= 2' data.csv로 두 번째 열이 2 이상인 행을 필터링하세요.
  4. awk -F',' '{ sum += $2 } END { print sum }' data.csv로 두 번째 열의 합계를 구하세요.
  5. cat Documents/notes.md | grep "항목" | wc -l로 항목 수를 세세요.

Q1. awk -F',' '$2 >= 80' scores.csv에서 -F','의 역할은?

  • A) 80보다 큰 값을 필터링하는 조건
  • B) 열 구분자를 쉼표로 지정
  • C) 파일 형식을 CSV로 지정
  • D) 두 번째 파일을 지정