awk

awk는 입력을 record와 field로 나누고, 각 record에 pattern을 검사한 뒤 대응하는 action을 실행하는 text 처리 언어이자 명령어다. 간단한 filtering, column 추출, 집계, report 생성에 적합하다. GNU 구현의 실행 파일 이름은 gawk이며 Linux에서는 awkgawk, mawk 또는 다른 구현을 가리킬 수 있다.

Unix 계열에는 보통 awk 구현이 기본 설치되어 있다. GNU 확장이 필요하거나 구현을 고정하려면 gawk package를 설치하고 script에서 gawk를 명시한다.

Debian 계열의 awk virtual package는 gawk, mawk, original-awk 같은 구현이 제공할 수 있다. GNU Awk를 명시적으로 설치하려면 다음을 사용한다.

sudo apt update
sudo apt install gawk
gawk --version

Fedora와 RHEL 계열에서는 gawk package가 awkgawk 실행 파일을 제공한다.

sudo dnf install gawk
gawk --version

macOS는 BSD 계열 awk를 기본 제공한다. GNU Awk가 필요하면 Homebrew formula를 설치한다. Homebrew는 GNU executable을 gawk로 제공하며, awk 이름을 우선 사용하려면 formula의 gnubin directory를 PATH 앞에 추가한다.

brew install gawk
gawk --version

공식 GNU Awk native winget package는 확인되지 않는다. Linux와 동일한 실행 환경이 필요하면 WSL을 설치하고 distribution 안에서 gawk를 설치한다.

wsl --install
sudo apt update
sudo apt install gawk
gawk --version
awk [OPTION...] 'PATTERN { ACTION }' [FILE...]
awk [OPTION...] -f PROGRAM_FILE [FILE...]
  • awk [OPTIONS…] PROGRAM [FILE…]
  • awk -f PROGRAM_FILE [FILE…]

입력을 지정하지 않으면 standard input을 읽는다. 기본 record separator는 newline이고 기본 field separator는 연속된 공백과 tab이다. $0은 현재 record 전체, $1부터 $NF까지는 field, NR은 전체 record 번호, FNR은 현재 file 안의 record 번호다.

awk -F: '{ print $1, $7 }' /etc/passwd
printf 'one two\nthree four\n' | awk '{ print NR, $1 }'
  • -F FS: 입력 field separator FS를 지정한다. 값은 shell에서 먼저 해석되지 않도록 보통 작은따옴표로 감싼다.
  • -f PROGRAM_FILE: awk program을 file에서 읽는다. 여러 번 지정하면 순서대로 결합한다.
  • -v VAR=VALUE: program 실행 전에 변수를 지정한다. BEGIN action에서도 사용할 수 있으며 여러 번 지정할 수 있다.

다음 option은 gawk 기준이며 다른 awk 구현에서는 지원하지 않을 수 있다.

  • -e PROGRAM_TEXT, –source=PROGRAM_TEXT: command line program source를 추가한다.
  • -i INCLUDE_FILE, –include=INCLUDE_FILE: awk source file을 include한다.
  • -l LIBRARY, –load=LIBRARY: dynamic extension을 load한다.
  • -L[fatal|invalid], –lint: 의심스럽거나 이식성이 낮은 구문을 진단한다.
  • -P, –posix: POSIX compatibility mode를 사용한다.
  • -S, –sandbox: system(), output redirection, input redirection과 dynamic extension load를 비활성화한다.
  • -p[FILE], –profile: 실행 profile을 작성한다.
  • -o[FILE], –pretty-print: program을 정규화해 출력한다.
  • –help: 도움말을 출력한다.
  • –version: version을 출력한다.

awk program은 pattern { action } rule의 연속이다.

  • BEGIN { action }: 첫 input record를 읽기 전에 한 번 실행한다.
  • pattern { action }: pattern이 참인 각 record에서 실행한다.
  • END { action }: 모든 input 처리가 끝난 뒤 실행한다.
  • pattern 생략: 모든 record에 action을 실행한다.
  • action 생략: pattern이 참인 record 전체를 출력한다. 즉 /ERROR//ERROR/ { print $0 }과 같다.
BEGIN { total = 0 }
$3 == "ERROR" { count[$2]++; total++ }
END {
    for (name in count)
        printf "%s %d\n", name, count[name]
    printf "total %d\n", total
}
이름 의미
$0 현재 record 전체
$1, $2, … 현재 record의 각 field
NF 현재 record의 field 수
NR 모든 input file을 합친 현재 record 번호
FNR 현재 input file 안의 record 번호
FS / OFS input / output field separator
RS / ORS input / output record separator
FILENAME 현재 input file 이름
ARGC / ARGV command line argument 수와 배열
ENVIRON environment variable 배열

print a, b는 값 사이에 OFS를 넣지만 print a b는 두 값을 separator 없이 문자열로 연결한다. 형식을 고정해야 하는 report에는 printf를 사용한다.

/PATTERN/은 현재 record 전체인 $0에 POSIX extended regular expression을 검사한다. 특정 field는 $1 ~ /PATTERN/ 또는 $1 !~ /PATTERN/처럼 검사한다.

awk '/^[[:space:]]*#/ { next } NF { print }' config.txt
awk '$3 ~ /^[[:digit:]]+$/ { print $1, $3 }' data.txt

기존 기록과 달리 awk regular expression에서도 backslash escape를 사용한다. 다만 /\\./ 같은 regexp literal과 "\\." 같은 string으로 전달하는 regexp는 parsing 단계가 달라 backslash 수가 달라질 수 있다. shell quoting까지 겹치는 경우 작은 test input으로 확인한다. 문자 class에는 locale 영향을 받는 [[:digit:]], [[:space:]] 같은 POSIX 표현을 사용할 수 있다.

기존의 field separator 예제를 보존한 형태다.

java -version 2>&1 | awk -F '"' '/version/ { print $2 }'
awk -F: '{ print $1, $3, $7 }' /etc/passwd
awk -F, -v OFS='\t' '{ print $1, $3 }' data.csv
단순히 -F, option을 사용하는 방식은 quoted comma, embedded newline, escaped quote가 있는 RFC 4180 CSV parser가 아니다. 이런 CSV에는 CSV-aware tool 또는 parser를 사용한다.
# 세 번째 field가 500 이상인 record
awk '$3 >= 500 { print $1, $3 }' data.txt
 
# ERROR부터 RECOVERED까지의 범위
awk '/ERROR/,/RECOVERED/' app.log
awk '{ sum += $1 } END { if (NR) print "sum", sum, "average", sum / NR }' values.txt

if (NR) 조건은 빈 input에서 0으로 나누는 일을 방지한다.

awk -F, '{ total[$1] += $2 } END { for (key in total) print key, total[key] }' data.csv

awk associative array의 순회 순서는 기본적으로 보장되지 않는다. 안정적인 출력 순서가 필요하면 외부 sort에 연결하거나 GNU Awk의 정렬 기능을 명시적으로 사용한다.

awk -F, '{ total[$1] += $2 } END { for (key in total) print key, total[key] }' data.csv |
    sort

첫 file의 첫 번째 field를 set에 저장하고, 두 번째 file에서 같은 key를 가진 record를 출력한다.

awk 'NR == FNR { wanted[$1] = 1; next } $1 in wanted' keys.txt records.txt

두 file이 모두 비어 있지 않은 일반적인 경우에 사용하는 관용구다. file 경계를 엄밀하게 처리해야 하거나 여러 file을 처리한다면 ARGIND 같은 GNU extension 또는 program 구조를 별도로 검토한다.

BEGIN { FS = ","; OFS = "\t" }
NR > 1 { total[$1] += $2 }
END {
    for (key in total)
        print key, total[key]
}
awk -f report.awk data.csv
  • shell variable을 program text에 직접 이어 붙이지 말고 -v name="$value"로 전달한다. quoting 오류와 의도하지 않은 awk code 삽입을 줄일 수 있다.
  • file 이름이 -로 시작할 수 있으면 implementation의 option parsing을 확인하고 를 지원하는 구현에서는 option 종결자로 사용한다.
  • locale에 따라 문자 class, 대소문자, 숫자와 decimal separator 동작이 달라질 수 있다. byte-oriented 또는 재현 가능한 parsing이 필요하면 목적을 확인한 뒤 LC_ALL=C를 제한적으로 사용한다.
  • untrusted awk program을 실행하지 않는다. awk의 system(), pipe와 redirection은 외부 command 실행 및 file 쓰기로 이어질 수 있다. GNU Awk에서는 제한된 실행에 –sandbox를 검토한다.
  • production script에서는 awk가 어느 구현인지 가정하지 말고 POSIX 기능만 사용하거나 shebang과 실행 command에서 필요한 구현을 명시한다.
  • awk: syntax error가 발생함: shell quote가 먼저 닫히지 않았는지, action의 brace와 string quote가 짝을 이루는지 확인한다. 복잡한 program은 -f file로 분리한다.
  • field가 예상과 다름: FS는 일반적으로 regular expression이며 기본 공백 분리에는 특별한 동작이 있다. 실제 delimiter와 빈 field 처리 요구를 확인한다.
  • variable 값이 전달되지 않음: shell variable은 -v option으로 전달한다. awk program을 감싼 작은따옴표 내부에서는 shell expansion이 일어나지 않는다.
  • macOS에서는 동작하지만 Linux 또는 그 반대에서 실패함: 사용 중인 awk 구현과 version을 확인하고 GNU extension을 사용했다면 gawk로 실행한다.
  • array 결과 순서가 실행마다 다름: for (key in array) 순서는 portable하게 보장되지 않는다. 출력 후 sort하거나 구현별 정렬 기능을 사용한다.
  • Windows text의 끝에 \r이 남음: CRLF input일 수 있다. data 형식을 고치거나 필요할 때만 sub(/\r$/, "")로 record 끝의 carriage return을 제거한다.

POSIX 공통 option은 -F, -f, -v다. GNU Awk는 long option, –sandbox, include, dynamic extension, profiling 등 추가 기능을 제공하지만 mawk, BSD awk, One True Awk에서는 동일하게 동작하지 않을 수 있다.

script의 portability가 중요하면 GNU Awk에서 –posix 또는 –lint로 검사하되, 이것만으로 모든 다른 구현의 동작을 보장하지는 않는다. regexp interval, multibyte 문자, locale, numeric string 비교와 extension function은 target 구현에서도 test한다.

awk --help (GNU Awk 4.2.1, local environment)

  • codex:: 2026-08-03 awk:ko language head page로 이동하고 설치, POSIX/GNU option, program 구조, field와 변수, regular expression, 안전한 예제, scripting, troubleshooting, compatibility와 실제 도움말을 추가했다.
  • /home/u613600155/domains/cli.zerotymer.net/public_html/data/pages/awk/ko.txt
  • 마지막으로 수정됨: 2026/08/03 13:10
  • 저자 127.0.0.1