[Linux]예제로 알아보는 awk 명령어 사용법
awk는 Daily Health Check Script blog에 사용된 명령어 중의 하나로 텍스트 데이터를 처리하고 보고서를 생성하는 데 사용되는 강력한 명령 줄 도구로 다양한 내장 함수와 제어 구조를 활용하여 원하는 작업을 수행할 수 있습니다. 정규표현식과 함께 사용하면 더욱 강력한 기능으로 사용할 수 있습니다.
awk
는 1970년대에 AT&T 벨 연구소에서 개발된 프로그래밍 언어로 “Aho, Weinberger, and Kernighan”의 이니셜을 따서 이름이 지어졌습니다.
일반적인 구문:
awk options scripts file
기본 옵션(options):
- -F seperator : 기본 구분자는 공백으로, 필드를 분리할 때 사용할 구분자를 지정(; 등)
- -f filename: 복잡한 스크립트를 외부 파일에 저장하고 실행
- -v var=value: 스크립트에서 사용할 변수를 정의하고, 초기값을 지정
내장 변수:
- NF: 필드 번호
- NR: 레코드 라인 변호
- FIELDWIDTHS: 필드 크기 지정
- RS: 레코드 구분자 지정(디폴트 \n)
- ORS: 출력 레코드 구분자 지정
- FS : 필드 구분자 지정(디폴트 공백)
- OFS : 출력 필드 구분자 지정
내장 함수:
- 수학 함수 : sin(x) | cos(x) | sqrt(x) | exp(x) | log(x) | rand()
- 문자열 함수 : tolower(str). touppper(str), length(str)
사용자 정의 함수:
- function func_name() { }
## 예제에서 사용할 예제 파일 내용 ## $ vi scores.txt class Q1 Q2 Q3 Q4 math 80 95 100 85 writing 83 87 91 95 history 75 79 87 92 ethics 65 70 87 93 society 94 83 86 77
- 파일 내용 출력
– 조건절: 라인 번호(NR), 필드번호(NF) 등을 사용하여 출력 조건 지정(NR!=1, NR>10, $1==”값” 등)
– 필드 : $n – n번째 필드, 생략하면 전체 내용 출력(==$0), $NF – 마지막 필드awk '[조건절] {print 필드}' filename
# awk '{print "origial:" $0 ",\t" $1"\t"$2"\t"$3"\t"$4"\t"$5}' scores.txt origial:class Q1 Q2 Q3 Q4, class Q1 Q2 Q3 Q4 origial:math 80 95 100 85, math 80 95 100 85 origial:writing 83 87 91 95, writing 83 87 91 95 origial:history 75 79 87 92, history 75 79 87 92 origial:ethics 65 70 87 93, ethics 65 70 87 93 origial:society 94 83 86 77, society 94 83 86 77 ## 레코드 또는 필드의 문자열 길이 검사 ## # echo -e "apple\norange\nbanana" | awk 'length($0)>5 {print $0}' orange banana ##첫번째 줄(헤더) 출력 제외 ## # awk 'NR!=1 {print $1"\t"$2"\t"$3"\t"$4"\t"$5}' scores.txt math 80 95 100 85 writing 83 87 91 95 history 75 79 87 92 ethics 65 70 87 93 society 94 83 86 77 ## 필드의 출력값 지정하기 ## # awk '$1=="math" {print $1"\t"$2"\t"$3"\t"$4"\t"$5}' scores.txt math 80 95 100 85 # awk '{if ($1=="math") print $1"\t"$2"\t"$3"\t"$4"\t"$5}' scores.txt math 80 95 100 85 ## 레코드 출력 범위 지정하기 ## # awk 'NR>2&&NR<5 {print NR": " $1"\t"$2"\t"$3"\t"$4"\t"$5}' scores.txt 3: writing 83 87 91 95 4: history 75 79 87 92 ## 출력 필드 너비 지정하기 ## # awk 'NR!=1 { printf "%-10s %3d %3d %3d %3d\n", $1, $2, $3, $4, $5}' scores.txt math 80 95 100 85 writing 83 87 91 95 history 75 79 87 92 ethics 65 70 87 93 society 94 83 86 77 - 구분자(delimiter/seperator)를 지정하여 출력
awk -F구분자 '{print 필드}' filename
# awk -F: '$1=="root" {print $1 ":" $3}' /etc/passwd root:0 - 특정 필드의 값을 변경하여 출력
awk '{$n = "value"; print $0}' filename
# echo "Hello John" | awk '{$2 = "Archer" ; print $0}' Hello Archer - 지정된 문자열을 포함하는 레코드만 출력
awk '/text/' filename
# awk '/t/' scores.txt math 80 95 100 85 writing 83 87 91 95 history 75 79 87 92 ethics 65 70 87 93 society 94 83 86 77 - 레코드 단위로 합계 구하기
- BEGIN { } : 선행처리(preprocessing)awk '{sum = 0} {sum += ($2+..+$N)} {print $0, sum}' filename
# awk 'NR!=1 {print $0}' scores.txt | awk 'BEGIN {print "class Q1 Q2 Q3 Q4 SUM AVG"}; {sum = 0} {sum += ($2+$3+$4+$5) } { print $0, sum, sum/4 }' class Q1 Q2 Q3 Q4 SUM AVG math 80 95 100 85 360 90 writing 83 87 91 95 356 89 history 75 79 87 92 333 83.25 ethics 65 70 87 93 315 78.75 society 94 83 86 77 340 85 - 필드 단위로 합계 구하기
- END { } : 후처리(postprocessing)awk '{sum += 필드}; END {print sum}' filename
# awk '{print $1"\t"$2"\t"$3"\t"$4"\t"$5}; {sum_q1 += $2};{sum_q2 +=$3}; {sum_q3 += $4};{sum_q4 +=$5}; END {print "total\t" sum_q1 "\t" sum_q2 "\t" sum_q3 "\t" sum_q4 }' scores.txt class Q1 Q2 Q3 Q4 math 80 95 100 85 writing 83 87 91 95 history 75 79 87 92 ethics 65 70 87 93 society 94 83 86 77 total 397 414 451 442 - 레코드 단위로 필드 중 최대 값 구하기
- while (조건절) { } : while loop 문
- for (시작; 조건; 증감) { } : for loop 문awk '{max = 0; for (i=2; i<=NF; i++) max = ($i > max) ? $i : max ; print $0, max}' filename
# awk 'NR!=1 {max = 0; for (i=2; i<=NF; i++) max = ($i > max) ? $i : max ; print $0, max}' scores.txt math 80 95 100 85 100 writing 83 87 91 95 95 history 75 79 87 92 92 ethics 65 70 87 93 93 society 94 83 86 77 94 - 전화번호 형식으로 출력
awk 'BEGIN{FIELDWIDTHS="3 4 4"; FS="-"}{print $0}' testfile
# echo "01012345678" | awk 'BEGIN{FIELDWIDTHS="3 4 4"; OFS="-"}; {print $1, $2, $3}' 010-1234-5678 - 사용자 정의 함수 예제
awk 'function func_name() { } BEGIN{ } { }' testfile
# awk 'function print_shell() { printf "The shell of (%s) user is %s\n", $1,$7 } BEGIN{FS=":"} { print_shell() }' /etc/passwd The shell of (root) user is /bin/bash The shell of (bin) user is /sbin/nologin ----- More ----- # vi awk.script function print_shell() { printf "The shell of (%s) user is %s\n", $1,$7 } BEGIN {FS=":"} { print_shell() } # awk -f awk.script /etc/passwd The shell of (root) user is /bin/bash The shell of (bin) user is /sbin/nologin ----- More -----