본문 바로가기
컴퓨터 & IT (Computer & IT)/Linux

[Linux] awk 사용법

by UltraLowTemp-Physics 2021. 6. 12.
728x90

awk는 유닉스에서 사용되는 고급 데이터 조작 기구이며, 프로그래밍에 가까운 작업환경을 제공한다. 이러한 awk를 사용하면 아래와 같은 작업들을 수행할 수 있다. 

  (a) 데이터를 저장하는 변수 정의 
  (b) 데이터를 다룰 수 있도록 산술 및 문자열 연산자 사용 
  (c) if-ten 및 루프문과 같이 데이터 처리에 로직을 추가하는 구조적 프로그래밍 개념 사용 
  (d) 데이터 파일 안에서 데이터 요소를 추출하고 다른 순서 또는 형식으로 재구성 


1. awk의 사용방법

1) awk의 syntax: $ awk <options> <program file> 

  • awk의 옵션 

옵션 설명
-F <IFS> 한 줄에서 데이터 필드의 경계를 식별하기 위한 파일 구분자를 지정함
NOTE: -F 옵션 말고 내장 변수인 FS를 사용하는 방법도 있다. 이는 아래 데이터 필드 변수 참조
-f <file> 프로그램이 읽어드릴 파일 이름을 지정 
-var=value awk 프로그램에서 사용할 변수의 기본값을 지정
-mf N 데이터 파일에서 처리할 필드의 최대 수를 지정
-mr N 데이터 파일의 최대 레코드 크기를 지정
-W keyword awk의 호환성 모드 또는 경고 수준을 지정

 

2) awk의 프로그램 스크립트 읽기: 
 - awk 프로그램의 스크립트는 열고 닫는 중괄호로 정의됨  
 - awk의 syntax: `awk '{print "string"}'`
 - 프로그램을 종료시키고자 한다면, `<ctrl>` + `<D>`를 눌러 bash에서 파일의 끝(`EOF`) 문자를 만들어 보낸다. 

3) 데이터를 처리하기 전에 스크립트 실행 

기본적으로 awk는 입력 스트림을 통해 한 줄의 텍스트를 읽고 그 텍스트 줄의 데이터에 대해 프로그램 스크립트를 실행한다. 때로는 보고서의 머리말 부분을 만들 때처럼 데이터를 처리하기 전에 스크립트를 실행시켜야 할 수도 있다. `BEGIN`은 이러한 일을 위해서 사용된다. 

  a.  `BEGIN` 키워드
    - awk이 데이터를 읽기 전에 프로그램 스크립트를 실행하도록 강제함 
    - `BEGIN` 키워드는 데이터를 처리하기 전에만 지정된 스크립트를 적용함 
  b. `END` 키워드 
    - awk이 데이터를 읽은 후 실행할 프로그램 스크립트를 지정할 수 있음 

  3-1) 예시 1

$ vim data.txt
Line 1 
Line 2 
Line 3

$ awk 'BEGIN {print "the Data file contents:"' 
> {print $0}
> END {print "End of file"}' data.txt
The Data file contents:
Line 1
Line 2
Line 3
End of File 

 

   3-2) 예시 2

$ vim awk_script.awk
BEGIN{
    print "The latest list of users and shells"
    print "USER ID \t Shell"
    print "---------- \t ---------"
    FS=":"
}
{
    print $1 "      \t " $7
}
END{
    print "This concludes the listing"
}

$awk -f awk_script.awk /etc/passwd

 

2. 세 가지 유형의 변수: 데이터 필드 변수, 내장 변수, 그리고 사용자 지정 변수

2.1. 데이터 필드 변수

2.1.1. 데이터 필드 변수
 a. 달러 기호 및 레코드 안에서 데이터 필드의 위치를 나타내는 숫자를 사용하여 데이터 레코드 안에서 데이터 필드의 위치를 참조 
 b. 데이터 필드는 필드 구분자에 의해서 구분됨 
    - "-F" 커맨드 라인 매개변수를 사용하거나 awk의 내장 변수인 FS를 사용하여 필드 구분자를 변경함  
    - 필드 구분자의 기본값(default): 빈칸 및 탭문자(화이트 스페이스)

2.1.2. 필드 레코드와 관련된 내장 변수 

변수 설명
FIELDWIDTHS 각 데이터 필드의 정확한 폭(칸의 수)를 정의한 숫자의 목록으로 빈칸으로 구분됨
>ex) 'BEGIN{FIELDWIDTHS="5 6 7 8"}':
 - 첫번째 출력 레코드의 길이: 5
 - 두번째 출력 레코드의 길이: 6
 - 세번째 출력 레코드의 길이: 7
 - 네번째 출력 레코드의 길이: 8
FS - 입력 필드 구분자
- 데이터 스트림에서 데이터 필드를 처리하는 방법을 정의
RS 입력 레코드 구분자
OFS 출력 필드 구분자
- 데이터 스트림에서 데이터 필드를 처리하는 방법을 정의
- 출력 시 필드 구분자들을 설정 
ORS 출력 레코드 구분자
FILENAME awk 프로그램에서 입력을 위해 사용되는 데이터 파일 이름
FNR 데이터 파일의 현재 레코드 번호
IGNORECASE 0이 아닌 값으로 설정하면 awk 명령에서 사용되는 문자열의 대소문자 구분을 무시
NF 마지막 데이터 필드
NR 처리된 입력 레코드의 수

 

2.1.3. 데이터 필드 변수 사용하기 
 - `awk`의 주요 기능 중 하나는 텍스트 파일 데이터를 자유롭게 조작할 수 있다는 점 
 - 자동으로 입력받은  줄의 각 데이터 요소를 변수에 할당함
 - 데이터 필드 변수 
   -- `$0` : 텍스트 전체 줄 
   -- `$1`: 텍스트의 줄에서 첫번째 데이터 필드 
   -- `$2`: 텍스트의 줄에서 두번째 데이터 필드 
   -- `$n`: 텍스트의 줄에서 n번째 데이터 필드 
 - 한 줄 안에서 각 데이터 필드는 필드 구분자에 의해서 분리됨
   -- awk의 기본 필드 구분자: 화이트 스페이스 (빈칸 및 탭 `\t`) 

※ NOTE: 다른 명령어와 같이 사용을 할 때는 파이프라인(|)을 통해서 사용한다. 
※ NOTE: awk 내에서 여러 명령들을 사용하고자 할 때에는 세미콜론(;)으로 구분 짓는다. 
ex) `awk '{print "Hello"; print "world"}'`

2.2. 데이터 필드 변수 사용의 예시 

Ex - 1) 데이터 필드의 사용 예시 
아래의 예시에선 21_pilots.txt 파일에서 각 줄의 첫번째 단어들을 읽는다. 

$vim 21_pilots.txt
I wake up fine and dandy but then by the time I find it handy
To rip my heart apart and start
Planning my crash landing
I go up, up, up, up, up to the ceiling
Then I feel my soul start leaving
$ awk '{print $1}' 21_pilots.txt
I
To
Planning
I
Then

 

Ex - 2) 옵션 `-F` 사용 (구분자 설정) 

$ awk -F: '{print $1}' /etc/passwd 

- `/etc/password` 파일에 있는 첫번째 데이터 필드만 표시를 함 
- `/etc/password` 파일은 각 데이터 요소를 ":"로 구분함 

 

Ex-3) 사용할 파일의 예시 

$ cat example.txt
data11:data12:data13:data14:data15:data16
data21:data22:data23:data24:data25:data26
data31:data32:data33:data34:data35:data36
data41:data42:data43:data44:data45:data46
data51:data52:data53:data54:data55:data56
data61:data62:data63:data64:data65:data66
data71:data72:data73:data74:data75:data76
data81:data82:data83:data84:data85:data16

 

   (1) FS 구분자의 예시 

$ awk 'BEGIN{FS=":"}{print $3,$4,$5}' example.txt
data13 data14 data15
data23 data24 data25
data33 data34 data35
data43 data44 data45
data53 data54 data55
data63 data64 data65
data73 data74 data75
data83 data84 data85

  - `{FS=":"}` : 필드 구분자를 ":"로 설정
  - `{print $3, $4, $5}`: 3~5번째 레코드 출력

   (2) OFS 내장 변수 사용 

$ awk 'BEGIN{FS=":"; OFS="-***-"}{print $3,$4,$5}' example.txt
data13-***-data14-***-data15
data23-***-data24-***-data25
data33-***-data34-***-data35
data43-***-data44-***-data45
data53-***-data54-***-data55
data63-***-data64-***-data65
data73-***-data74-***-data75
data83-***-data84-***-data85

  - `FS=":"` : 필드 구분자를 ":"로 설정
  - `OFS="-***-"` : 출력시 레코드 간의 구분자를 "-***-"로 설정
  - `{print $3, $4, $5}`: 3~5번째 레코드 출력

   (3) NF 내장 변수 사용 (마지막 레코드)

$ awk 'BEGIN{FS=":"; OFS="-***-"}{print $1,$NF}' example.txt
data11-***-data16
data21-***-data26
data31-***-data36
data41-***-data46
data51-***-data56
data61-***-data66
data71-***-data76
data81-***-data16

 

   (4) FNR 및 NR 내장 변수 사용 

$ awk 'BEGIN{FS=":"; OFS="-***-"}{print $1,$NF, "FNR="FNR, "NR="NR}' example.txt example.txt
data11-***-data16-***-FNR=1-***-NR=1
data21-***-data26-***-FNR=2-***-NR=2
data31-***-data36-***-FNR=3-***-NR=3
data41-***-data46-***-FNR=4-***-NR=4
data51-***-data56-***-FNR=5-***-NR=5
data61-***-data66-***-FNR=6-***-NR=6
data71-***-data76-***-FNR=7-***-NR=7
data81-***-data16-***-FNR=8-***-NR=8
data11-***-data16-***-FNR=1-***-NR=9
data21-***-data26-***-FNR=2-***-NR=10
data31-***-data36-***-FNR=3-***-NR=11
data41-***-data46-***-FNR=4-***-NR=12
data51-***-data56-***-FNR=5-***-NR=13
data61-***-data66-***-FNR=6-***-NR=14
data71-***-data76-***-FNR=7-***-NR=15
data81-***-data16-***-FNR=8-***-NR=16

  - `FNR`은 파일 1개당 레코드의 번호를 의미
  - `NR`은 awk 프로그램이 처리한 레코드의 갯수를 의미


3. awk과 정규 표현식 사용

※ awk 프로그램에서 정규 표현식을 사용하기 위해선, 정규 표현식이 이를 제어하는 프로그램 스크립트의 왼쪽 중괄호 앞에 나와야 한다. 가령, 아래와 같은 예제 파일이 있다고 하자. 

$ cat example.txt
APPLE:data11:data12:data13:data14:data15:data16
APPLE:data21:data22:data23:data24:data25:data26
APPLE:data31:data32:data33:data34:data35:data36
BANANA:data41:data42:data43:data44:data45:data46
BANANA:data51:data52:data53:data54:data55:data56
BANANA:data61:data62:data63:data64:data65:data66
BANANA:data71:data72:data73:data74:data75:data76
BANANA:data81:data82:data83:data84:data85:data16

 

(1) 정규 표현식을 사용하여 APPLE이 나오는 데이터 필드만 추출 

$ awk 'BEGIN{FS=":"; OFS="-***-"}/APPLE/{print $2}' example.txt
data11
data21
data31

 

(2) 정규 표현식을 사용하여 BANANA가 나오는 데이터 필드만 추출

$ awk 'BEGIN{FS=":"; OFS="-***-"}/BANANA/{print $2}' example.txt
data41
data51
data61
data71
data81

 

(3) 대조 연산자를 사용하여 특정 데이터 필드로 정규 표현식을 제한 
   • 대조 연산자의 기호: ~ 

$ awk 'BEGIN{FS=":"; OFS="-***-"} $2 ~ /^data1|^data4/{print $0}' example.txt
APPLE:data11:data12:data13:data14:data15:data16
BANANA:data41:data42:data43:data44:data45:data46

• `$2 ~/^data1|^data4` : 두번째 필드의 레코드가 `data1` 혹은 `data4`로 시작되는 문자열일 경우에만 추출 

 

4. awk에서 많이 사용하는 내장 함수들 

4.0. 기본적인 내장 함수들

  • awk과 구조적 명령: `if`, `for`, `while`, `do-while`   
  • 서식화된 출력: `printf`
     - syntax: `printf "format string", var1, var2, ...`
     - formatring string은 c 언어에서의 format과 동일한 형식이다. 
    - 예시: 

$cat example.txt
apple  0.234 0.12
banana 1.232 1.3
water_melon 4.452 4.3
lemon 2.33 0.2354

$ awk '{printf "type: %-15s  price: $ %-6.2f weigth: %-6.4f kg\n", $1, $2, $3}' example.txt
type: apple            price: $ 0.23   weigth: 0.1200 kg
type: banana           price: $ 1.23   weigth: 1.3000 kg
type: water_melon      price: $ 4.45   weigth: 4.3000 kg
type: lemon            price: $ 2.33   weigth: 0.2354 kg

 

4.1 수학 함수들

아래와 같은 수학함수들이 존재한다:  `atan2(x,y)`, `cos(x)`, `exp(x)`, `int(x)`, `log(x)`, `rand(x)`, `sin(x)`, `sqrt(x)`, `srand(x)` 

4.2. 비트 조작 함수 

함수 설명
and(v1,v2) v1과 v2에 대해 비트 and 연산을 수행
compl(val) val에 대한 비트 단위 보수 계산 수행
lshift(val, count) val의 비트를 count 수만큼 왼쪽으로 이동
or(v1,v2) v1과 v2에 대해 비트 or 연산을 수행
xor(v1,v2) v1과 v2에 대해 비트 xor연산을 수행

 

4.3. 시간 함수 

함수  설명
mktime(datespec) YYY MM DD HH MM SS [DST] 형식으로 지정된 시간 값을 타임 스탬프 값으로 바꿈
strftime(format[, timestamp] 현재 시간의 날짜 타임 스탬프, 또는 제공되는 타임 스탬프를 date() 쉘 함수 형식을 사용하여 형식화된 시간과 날짜 형식으로 만듬
systime() 현재 시간에 대한 타임 스탬프 값을 줌

 

사용 예시 1) 

$ awk 'BEGIN{
> date = systime()
> dat = strftime("%A, %B %d, %Y", date)
> print day
}
Friday, December 26, 2014

 

5. 사용자 정의 함수 

• 요약: `function` 키워드를 사용 
• syntax

#syntax
function name([variables])
{
	statements
}

awk 함수 라이브러리를 이용할 경우
  a. awk로 작성한 함수들이 있는 하나의 파일을 작성함 
  b. awk 프로그램을 실행시킬 때, `-f` 옵션을 사용하여, 해당 파일을 불러온다.
Ex) 만일 `func1.awk`, `func2.awk`이란 파일에 각각 awk 함수들이 저장되어 있다고 가정하자. 이때, 파일에 저장된 특정 함수들을 불러오기 위해서, 아래와 같은 명령어를 입력한다: `$ awk -f func1.awk -f func2.awk <awk_command>` 

 

728x90

댓글