[리눅스 명령어] awk 사용법

[리눅스 명령어] awk 사용법

안녕하세요? 정리하는 개발자 워니즈입니다. 이번시리즈는 awk 명령어에 대해서 정리를 해보는 시간을 갖어보려고 합니다.

리눅스에서는 다양한 명령어가 있지만, 그중에서 자주 사용하고 특히 정리가 필요로 하는 부분은 정리를 하고자 합니다.

awk 명령어(1/3)
sed 명령어(2/3)
cut 명령어(2/3)

  • awk 명령어(1/3)
  • cut 명령어(2/3)
  • sed 명령어(3/3)

위의 명령어들을 정리해볼 예정이고, 순차적으로 작성을 해볼 생각입니다.
awk cheatsheet

1. awk 명령어란?

awk 란 패턴 탐색과 처리를 위한 명령어로 간단하게 파일에서 결과를 추려내고 가공하여 원하는 결과물을 만들어내는 유틸리티입니다.

즉 파일에서 패턴이 일치하는 행을 찾아서 지정한 조치를 수행해주는 명령어이다. awk 명령은 사용자가 정의한 명령어 집합을 이용하여 파일 집합과 사용자가 제공한 확장 표현식을 한번에 한 행씩 비교한 다음 확장 정규식과 일치하는 모든 행에 작용하여 특별한 작업을 해 준다.

초기 개발자 Aho, Weinberger, Kernighan의 첫글자를 따서 이름지어진 awk는 GNU 프로젝트에서 만들어진 텍스트 처리 프로그래밍 언어로 유닉스 계열의 OS에서 사용 가능하며, 텍스트 형태로 되어있는 입력 데이터를 행과 단어 별로 처리해 출력한다.

awk 명령

2. awk 기본 명령어

awk [OPTION...] [awk program] [ARGUMENT...]
      OPTION
        -F        : 필드 구분 문자 지정.
        -f        : awk program 파일 경로 지정.
        -v        : awk program에서 사용될 특정 variable값 지정.
      awk program
        -f 옵션이 사용되지 않은 경우, awk가 실행할 awk program 코드 지정.
      ARGUMENT
        입력 파일 지정 또는 variable 값 지정.

awk 명령을 통해 주로 하는 명령은 다음과 같습니다.

  • 텍스트 파일의 전체 내용 출력.
  • 파일의 특정 필드만 출력.
  • 특정 필드에 문자열을 추가해서 출력.
  • 패턴이 포함된 레코드 출력.
  • 특정 필드에 연산 수행 결과 출력.
  • 필드 값 비교에 따라 레코드 출력.

2-1. awk 기본 구조

 pattern { action }

2-2. awk program

awk [OPTION...] 'pattern { action }' [ARGUMENT...]

awk 명령에서 awk program은 ‘ ‘(single quotation marks) 안에 작성합니다.

아래와 같이 pattern이 생략되는 경우, 매칭 여부를 검사할 문자열 패턴 정보가 없기 때문에 모든 레코드가 선택되고, action을 생략하면, 기본 액션인 print가 실행되는 것입니다.

# pattern 생략.
$ awk '{ print }' ./file.txt      # file.txt의 모든 레코드 출력.

# action 생략.
$ awk '/p/' ./file.txt            # file.txt에서 p를 포함하는 레코드 출력.

2-3. awk record 적용 방식

pattern과 action에 작성되는 awk program 코드에는 다양한 표현식, 변수, 함수 등이 사용됩니다. 이 중 가장 중요한 변수는 레코드와 필드를 나타내는 변수인데, 하나의 레코드는 $0, 레코드에 포함된 각 필드는 그 순서대로 $1, $2, …, $n 으로 지칭됩니다.

awk bash beginners

3. awk 사용예제

필자는 주로 awk ‘{print $1}’ 과 같이 단순히 record를 출력해서 사용하는 방법에 대해서만 알고있지만, 아래와 같이 다양한 사용법이 있고, program도 넣어서 만들 수 있기에 다양하게 활용될 수 있다.

awk 사용 예 명령어 옵션
파일의 전체 내용 출력 awk ‘{ print }’ [FILE]
필드 값 출력 awk ‘{ print $1 }’ [FILE]
필드 값에 임의 문자열을 같이 출력 awk ‘{print “STR”$1, “STR”$2}’ [FILE]
지정된 문자열을 포함하는 레코드만 출력 awk ‘/STR/’ [FILE]
특정 필드 값 비교를 통해 선택된 레코드만 출력 awk ‘$1 == 10 { print $2 }’ [FILE]
특정 필드들의 합 구하기 awk ‘{sum += $3} END { print sum }’ [FILE]
여러 필드들의 합 구하기 awk ‘{ for (i=2; i<=NF; i++) total += $i }; END { print "TOTAL : "total }' [FILE]
레코드 단위로 필드 합 및 평균 값 구하기 awk ‘{ sum = 0 } {sum += ($3+$4+$5) } { print $0, sum, sum/3 }’ [FILE]
필드에 연산을 수행한 결과 출력하기 awk ‘{print $1, $2, $3+2, $4, $5}’ [FILE]
레코드 또는 필드의 문자열 길이 검사 awk ‘ length($0) > 20’ [FILE]
파일에 저장된 awk program 실행 awk -f [AWK FILE] [FILE]
필드 구분 문자 변경하기 awk -F ‘:’ ‘{ print $1 }’ [FILE]
awk 실행 결과 레코드 정렬하기 awk ‘{ print $0 }’ [FILE]
특정 레코드만 출력하기 awk ‘NR == 2 { print $0; exit }’ [FILE]
출력 필드 너비 지정하기 awk ‘{ printf “%-3s %-8s %-4s %-4s %-4s\n”, $1, $2, $3, $4, $5}’ [FILE]
필드 중 최대 값 출력 awk ‘{max = 0; for (i=3; i max) ? $i : max ; print max}’ [FILE]

3.1 파일의 전체 내용 출력.

awk 파일에 “print” 액션만 지정한 경우, 입력으로 지정된 파일의 내용을 출력합니다.

$ awk '{ print }' ./file.txt            > file.txt의 전체 파일 내용 출력.
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{ print }' ./file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

3.2 필드 값 출력.

“print $n” 액션을 통해 n번째 필드 값을 출력할 수 있습니다. 참고로, “$0″은 전체 레코드를 나타내는 변수입니다.

$ awk '{ print $2 }' ./file.txt           > 두 번째 필드 값 출력.
$ awk '{ print $1,$2 }' ./file.txt        > 첫 번째, 두 번째 필드 값 출력.
$ awk '{ print $0}' ./file.txt            > 레코드 출력.
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{ print $1, $2}' ./file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

3.3 필드 값에 임의 문자열을 같이 출력.

awk '{print "no:"$1, "user:"$2}' ./file.txt
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{print "no:"$1, "user:"$2}' ./file.txt
no:1 user:ppotta
no:2 user:soft
no:3 user:prog

3.4 지정된 문자열을 포함하는 레코드만 출력.

awk의 패턴에 정규 표현식(Regular Expression)을 사용하여 문자열 패턴을 검사할 수 있습니다. 이 때, 정규 표현식은 “/regex/” 형태로 지정할 수 있습니다.

awk '/pp/' ./file.txt                   # "pp" 가 포함된 레코드만 유효.
awk '/[2-3]0/' ./file.txt               # 20, 30 이 포함된 레코드만 유효.
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '/pp/' ./file.txt
1 ppotta 30 40 50

$ awk '/[2-3]0/' ./file.txt
1 ppotta 30 40 50
3 prog   90 10 20

3.5 특정 필드 값 비교를 통해 선택된 레코드만 출력.

awk program language의 표현식을 사용하여, 유효한 레코드를 위한 필드 값을 비교할 수 있습니다.

awk '$1 == 2 { print $2 }' ./file.txt   # 첫 번째 필드가 2인 레코드의 두 번째 필드 출력.
awk '$3 > 70 { print $0 }' ./file.txt   # 세 번째 필드가 70보다 큰 레코드 출력.
awk '$3 == 30 && $4 ==40 { print $2 }' file.txt   # 세 번째 필드가 30이고 네 번째 필드가 40인 레코드의 두 번째 필드 출력.
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '$1 == 2 { print $2 }' ./file.txt
soft

$ awk '$3 > 70 { print $0 }' ./file.txt
3 prog   90 10 20

$ awk '$3 == 30 && $4 ==40 { print $2 }' file.txt
ppotta

3.6 지정된 필드의 값을 더한 값 출력. (특정 필드에 대한 합 구하기)

awk program에서 변수의 사용을 통해 특정 필드의 값을 더하고, 더해진 총 합을 출력할 수 있습니다. 이 때, 총합은 모든 레코드 탐색이 끝난 시점인, “END” 패턴의 액션에서 실행합니다.

awk '{sum += $3} END { print sum }' ./file.txt
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{sum += $3} END { print "SUM : "sum }' ./file.txt
SUM : 180

3.7 여러 필드의 값을 더한 값 출력. (여러 필드에 대한 합 구하기)

for 루프를 수행하여 여러 필드의 값을 연산에 포함시킬 수 있습니다. 참고로 아래 예제에서 “NF”는 현재 레코드의 필드 갯수를 뜻하며, “$i”는 변수 i가 매핑된 필드를 뜻합니다. (i=2일 때 $2)

awk '{ for (i=2; i<=NF; i++) total += $i }; END { print "TOTAL : "total }' ./file.txt
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{ for (i=2; i<=NF; i++) total += $i }; END { print "TOTAL : "total }' ./file.txt
TOTAL : 450

3.8 레코드 단위로 필드 합 및 평균 값 구하기.

변수 및 액션을 조합하여 레코드 단위로 필드들의 값 및 평균을 계산하여 출력할 수 있습니다.

awk '{ sum = 0 } {sum += ($3+$4+$5) } { print $0, sum, sum/3 }' ./file.txt
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{ sum = 0 } {sum += ($3+$4+$5) } { print $0, sum, sum/3 }' ./file.txt
1 ppotta 30 40 50 120 40
2 soft   60 70 80 210 70
3 prog   90 10 20 120 40

3.9 필드에 연산을 수행한 결과 출력하기.

awk program 표현식을 사용하여, 필드에 연산을 수행한 결과를 출력할 수 있습니다.

awk '{print $1, $2, $3+2, $4, $5}' ./file.txt     # 세 번째 필드에 2를 더한 값을 출력.
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{print $1, $2, $3+2, $4, $5}' ./file.txt
1 ppotta 32 40 50
2 soft 62 70 80
3 prog 92 10 20

3.10 레코드 또는 필드의 문자열 길이 검사.

length() 함수를 사용해 레코드 또는 필드의 문자열 길이를 확인할 수 있습니다.

awk ' length($0) > 20' ./file.txt               # 레코드의 길이가 20보다 큰 경우.
awk ' length($2) > 4 { print $0 } ' ./file.txt  # 두 번째 필드의 길이가 4보다 큰 레코드 출력.
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk ' length($2) > 4 { print $0 } ' ./file.txt
1 ppotta 30 40 50

3.11 파일에 저장된 awk program 실행.

awk 실행 시, "-f" 옵션을 사용하여 파일로부터 awk program을 실행할 수 있습니다.

awk -f awkp.script ./file.txt           # awkp.script에 저장된 awk program 실행
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ cat awkp.script
{
    for (i=2; i<=NF; i++)
        total += $i
}

END {
    print "TOTAL : "total
}

$ awk -f awkp.script ./file.txt
TOTAL : 450

3.12 필드 구분 문자 변경하기.

기본적으로 레코드의 필드를 구분하는 문자는 space 입니다. 이를 "-F" 사용하여 변경할 수 있습니다.

awk -F ':' '{ print $1 }' ./file.txt         # 필드 구분 문자를 : 로 변경.
awk -F ',' '{ print $1 }' ./file.txt         # 필드 구분 문자를 , 로 변경.

$ cat file2.txt
1, ppotta, 30, 40, 50
2, soft,   60, 70, 80
3, prog,   90, 10, 20

$ awk -F ',' '{ print $1 }' ./file2.txt
1
2
3

3.13 awk 실행 결과 레코드 정렬하기.

awk 명령과 sort 명령을 조합하여, awk 실행 결과로 출력되는 레코드를 정렬할 수 있습니다.

awk '{ print $0 }' file.txt | soft      # 출력 레코드를 오름차순으로 정렬.
awk '{ print $0 }' file.txt | sort -r   # 출력 레코드를 역순으로 정렬.

$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{ print $0 }' file.txt | sort -r
3 prog   90 10 20
2 soft   60 70 80
1 ppotta 30 40 50

3.14 특정 레코드만 출력하기.

exit 키워드를 사용하여, 조건에 따라 awk 실행을 중지시킬 수 있습니다.

awk '{ print $0; exit }' file.txt       # 첫 번째 레코드만 출력하고 실행 중지.
awk 'NR == 2 { print $0; exit }' file.txt         # 두 번째 레코드만 출력하고 실행 중지.
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk 'NR == 2 { print $0; exit }' file.txt
2 soft   60 70 80

3.15 출력 필드 너비 지정하기.

printf 함수를 사용하여 필드 값 출력 포맷을 지정할 수 있습니다. printf 함수에 사용하는 출력 포맷은 C 언어와 동일합니다.

awk '{ printf "%-3s %-8s %-4s %-4s %-4s\n", $1, $2, $3, $4, $5}' file.txt
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20
$ awk '{ printf "%-3s %-8s %-4s %-4s %-4s\n", $1, $2, $3, $4, $5}' file.txt
1   ppotta   30   40   50  
2   soft     60   70   80  
3   prog     90   10   20

3.16 필드 중 최대 값 출력.

아래와 같은 코드를 통해 레코드 내 필드의 최대 값을 구하여 출력할 수 있습니다.

awk '{max = 0; for (i=3; i max) ? $i : max ; print max}' ./file.txt
$ cat file.txt
1 ppotta 30 40 50
2 soft   60 70 80
3 prog   90 10 20

$ awk '{max = 0; for (i=3; i max) ? $i : max ; print max}' ./file.txt
40
70
90

4. 마치며...

awk 사용법에 대해서 정리를 하면서, 사실 필자가 지금까지 사용해오던것은 정말 기초적인 수준이구나 하는 것을 느끼게 되었습니다. 단순히 print 를 하는것에서만 사용했다면, 이제는 간단한 program logic도 넣을 수 있을것 같습니다.

많은 회사들에서 쉘을 다뤄봤다면, awk 스크립트를 사용할 줄 아냐고 묻는 이유를 이제서야 알것 같습니다.
다음시간에는 필자가 지금까지 만들어왔던 shell script들에 대해서 작성해볼 예정입니다.

이후에는 cut, sed 에 대해서도 정리할 예정이니 많은 기대 부탁드립니다.😄

워니즈 블로그
워니즈 깃헙

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다