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>`
'컴퓨터 & IT (Computer & IT) > Linux' 카테고리의 다른 글
[Linux] 모니터링과 관련된 명령어 (du, df) (0) | 2021.06.26 |
---|---|
[Linux] 런레벨 확인 및 변경 (0) | 2021.06.12 |
[Linux] 터미널이 종료 후 프로그램 계속 실행시키기 (&, &&, nohup) (0) | 2021.05.06 |
[Linux] screen 명령어 (0) | 2021.04.27 |
[Linux] GPU 모니터링 (0) | 2021.04.27 |
댓글