목차

, , , , , ,

awk

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

Installation

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

Debian / Ubuntu

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

sudo apt update
sudo apt install gawk
gawk --version

Fedora / RHEL

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

sudo dnf install gawk
gawk --version

macOS

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

brew install gawk
gawk --version

Windows

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

wsl --install
sudo apt update
sudo apt install gawk
gawk --version

Usage

awk [OPTION...] 'PATTERN { ACTION }' [FILE...]
awk [OPTION...] -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 }'

Options

POSIX options

주요 GNU Awk extensions

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

Program Structure

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

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
}

Fields and Variables

이름 의미
$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를 사용한다.

Regular Expressions

/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 표현을 사용할 수 있다.

Examples

Java version 추출

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

java -version 2>&1 | awk -F '"' '/version/ { print $2 }'

Column 선택과 separator 지정

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를 사용한다.

조건으로 record filtering

# 세 번째 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으로 나누는 일을 방지한다.

Key별 집계

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 비교

첫 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 구조를 별도로 검토한다.

Program file 사용

BEGIN { FS = ","; OFS = "\t" }
NR > 1 { total[$1] += $2 }
END {
    for (key in total)
        print key, total[key]
}
awk -f report.awk data.csv

Scripting Notes

Troubleshooting

Compatibility

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한다.

Help

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

See Also

History