iBetter Books
수정

필드와 레코드 처리

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를 활용하면 깔끔한 보고서 형식을 만들 수 있습니다. 다음 절에서는 패턴의 종류와 변수, 배열, 함수를 살펴보겠습니다.