필드와 레코드 처리
awk의 진짜 강점은 데이터를 구조적으로 다루는 데 있습니다. 각 줄을 레코드(record), 줄 안의 각 항목을 필드(field)로 봅니다. 내장 변수들이 이 구조를 제어합니다.
내장 변수
| 변수 | 의미 | 기본값 |
|---|---|---|
NR |
현재까지 읽은 레코드(줄) 번호 | - |
NF |
현재 레코드의 필드 수 | - |
FS |
입력 필드 구분자 | 공백 |
RS |
입력 레코드 구분자 | 개행 |
OFS |
출력 필드 구분자 | 공백 |
ORS |
출력 레코드 구분자 | 개행 |
필드 재구성
필드 변수는 읽기뿐만 아니라 쓰기도 가능합니다. $2 = "새값"처럼 직접 대입하면 해당 필드가 바뀝니다.
echo "Alice 30 Seoul" | awk '{ $2 = 31; print }'
Alice 31 Seoul
OFS로 출력 구분자 변경.
print $1, $2에서 쉼표는 OFS로 필드를 이어 붙입니다. OFS를 바꾸면 출력 형식이 바뀝니다.
echo "Alice 30 Seoul" | awk 'BEGIN { OFS="," } { print $1, $2, $3 }'
Alice,30,Seoul
공백으로 구분된 데이터를 CSV로 변환하는 간단한 방법입니다.
조건부 출력
패턴 위치에 비교 연산자를 씁니다.
cat /tmp/scores.csv | awk -F, 'NR > 1 && $4 > 80 { print $1, $4 }'
Alice 88
Carol 91
&&는 AND 조건입니다. NR > 1(헤더 제외)이면서 수학 점수가 80 초과인 줄만 처리합니다.
범위 조건.
# 점수가 70 이상 90 미만인 학생awk -F, 'NR > 1 && $2 >= 70 && $2 < 90 { print $1, $2 }' /tmp/scores.csv
Alice 85
Bob 72
printf로 정렬 출력
print는 단순 출력이고, printf는 C 언어와 동일한 포맷 문자열을 사용합니다.
| 포맷 | 의미 |
|---|---|
%s |
문자열 |
%d |
정수 |
%f |
실수 |
%-10s |
왼쪽 정렬, 10칸 |
%5d |
오른쪽 정렬, 5칸 |
# 헤더와 데이터를 정렬해서 출력awk -F, 'NR == 1 { printf "%-10s %5s %5s %5s\n", $1, $2, $3, $4 }NR > 1 { printf "%-10s %5d %5d %5d\n", $1, $2, $3, $4 }' /tmp/scores.csv
이름 국어 영어 수학
Alice 85 92 88
Bob 72 68 80
Carol 95 89 91
Dave 60 74 65
%-10s는 왼쪽 정렬 10칸, %5d는 오른쪽 정렬 5칸입니다. printf는 자동 줄바꿈이 없으므로 \n을 직접 넣어야 합니다.
필드 수 활용
NF를 활용하면 비정형 데이터도 처리할 수 있습니다.
cat > /tmp/mixed.txt << 'EOF'Alice 85 92 88Bob 72 68Carol 95 89 91 78Dave 60EOF# 필드가 3개 이상인 줄만 출력awk 'NF >= 3 { print NR, NF, $0 }' /tmp/mixed.txt
1 4 Alice 85 92 88
3 4 Carol 95 89 91 78
실습. 성적 데이터 분석
국어, 영어, 수학 세 과목의 평균을 계산하고 80점 이상인 학생을 정렬해서 출력합니다.
awk -F, 'BEGIN { printf "%-10s %7s %7s %7s %7s\n", "이름", "국어", "영어", "수학", "평균" print "──────────────────────────────────────────"}NR > 1 { avg = ($2 + $3 + $4) / 3 if (avg >= 80) { printf "%-10s %7d %7d %7d %7.1f\n", $1, $2, $3, $4, avg }}' /tmp/scores.csv | sort -k5 -rn
──────────────────────────────────────────
이름 국어 영어 수학 평균
Carol 95 89 91 91.7
Alice 85 92 88 88.3
Bob 72 68 80 73.3
잠깐, sort가 헤더도 정렬해버렸습니다. BEGIN 블록의 헤더는 awk가 처리하지만, 파이프를 통과하면 sort가 모든 줄을 정렬합니다. 헤더를 고정하려면 별도로 출력하거나, sort 후 헤더를 다시 붙이는 방법을 씁니다.
# 헤더 따로 출력 후 데이터만 sort{ echo -e "이름\t국어\t영어\t수학\t평균" awk -F, 'NR > 1 { avg = ($2 + $3 + $4) / 3 if (avg >= 80) printf "%s\t%d\t%d\t%d\t%.1f\n", $1, $2, $3, $4, avg }' /tmp/scores.csv | sort -t$'\t' -k5 -rn}
이름 국어 영어 수학 평균
Carol 95 89 91 91.7
Alice 85 92 88 88.3
awk의 내장 변수와 printf를 활용하면 깔끔한 보고서 형식을 만들 수 있습니다. 다음 절에서는 패턴의 종류와 변수, 배열, 함수를 살펴보겠습니다.