awk 사용법#1에서 알아보았듯이
awk program의 구조는

BEGIN {
actions A
}

[condition B] {
actions B
}

[condition C] {
actions C
}

                 .
                 .
                 .

END {
actions D
}

와 같이 나누어 진다.

일단 condition에 들어갈 수 있는 내용은 C 프로그램에서 if문에 들어갈 수 있는 내용과 거의 동일하다. 그 유형은 크게 3가지로 나눌 수 있는데

1. Condtion이 존재하지 않을 때
이는 모든 입력 record에 대해서 괄호 안의 action을 모두 수행하는 것을  의미한다.
2. /RE(Regular expression)/
해당 record가 RE의 내용을 포함하고 있다면 괄호 안의 action을 모두 수행한다.
3. 조건문
조건문이 만족할 경우 괄호 안의 action을 모두 수행한다.

이들을 예를 들어 확인해 보자.

{
print "A";
}

/[0-9]+ {
print "B";
}

NF==9 {
print "C";
}

위는 하나의 awk 프로그램이다.
awk는 record를 하나씩 가져와 이들을 모두 수행하는데,
첫번째 괄호의 경우 condition이 주어져 있지 않으므로 A라는 문자를 무조건 출력한다.
두번째 괄호의 경우 record가 숫자를 포함하고 있다면 B라는 문자를 출력한다.
세번째 괄호의 경우 NF라는 변수가 9인 경우 C라는 문자를 출력한다.


이제 programming을 하기 전에
constant, variable operator에 대해서 알아보도록 한다.


1. Constant
Constant는 string과 numeric으로 나누어 진다.
String은 문자열로 큰 따옴표로 둘러쌓인 모든 문자를 뜻한다.
Numeric은 숫자로 정수, 소수점을 모두 포함한다.


2. Variable
Variable은 constant를 저장하고 있는 변수이다.
이는 따로 선언할 필요필요가 없고, 대소문자를 구분한다.

예를 들어
x=1                         # x에 숫자 1을 넣는다.
x="Hello"              # x에 문자열 "Hello"를 넣는다.
x="Hello" "World"  # x에 문자열 "HelloWorld"를 넣는다. (Concatenation)
x=$1                       # x에 첫번째 field의 내용을 넣는다.

Variable 중에 특별히 system variable이 존재한다.
이는 reserved word로 다른 변수로 사용할 수 없다.
자주 쓰이는 system variable의 종류와 그 쓰임새는 다음과 같다.

FS
    Field separtor, 앞서 설명한 것과 같이 field를 구분해주는 단위를 바꿔주고 싶다면 이것을 바꾸어 주면 된다. 예) FS="\t+" - 한개 또는 그 이상의 tab 여백.

OFS
    Output field separator, 출력시 field를 구분해 주는 단위.

RS
    Record separator, 앞서 설명한 것과 같이 record를 구분해주는 단위를 바꿔주고 싶다면 이것을 바꾸어 주면 된다. 예) RS="" - 아무것도 쓰여져 있지 않은 line.

ORS
    Output record separator, 출력시 record를 구분해 주는 단위.

NR
    Number of current input record, 해당 record가 전체 텍스트의 몇번째 record인지 나타내는 변수.

NF
    The number of fields in current input record, 해당 record의 총 field의 개수.

FILENAME
    The name of the current input file, 지금 수행하고 있는 file의 이름.

FNR
    Number of current input record relative to the current input file, 지금 수행하고 있는 record가 지금 수행하고 있는 record의 몇번째 record인지 나타내는 변수. (c.f. NR은 여러개의 파일을 수행할 때 이들 파일을 하나로 보아 총 record의 개수를 나타낸다.)

이중 FS, OFS, RS, ORS의 경우 프로그램 중간에서 바뀌면 프로그램의 작동에 크게 영향을 주므로 BEGIN{} 에서 이들을 지정해주는 편이 좋다.
나머지 system variable의 경우 프로그램 작성시 사용하면 유용하다.


3. Operator
Operator는 크게 arithmetic, assignment, relational, boolean operator로 나누어진다.

Arithmetic operators: +, -, *, /, %(modulo), ^(exponential)
Assignment operators: ++, --, +=, -=, *=, /=, %=, ^=
Relational operators: <, >, <=, >=, ==, !=, ~(match), !~(Does not match)
Boolean operators: ||, &&, !

모두 C programming에서 사용하는 것이지만
이중 생소한 것이 ~와 !~ opeator일 것이다.
~는 왼쪽 문자열을 오른쪽 문자열에 pattern-matching을 하여 matching이 되면 true가 된다.
오른쪽 operand로는 /RE/, variable, constant 모두가 나올 수 있다. 그리고 이들은 모두 RE로 받아들이게 되고, 이들을 왼쪽 문자열이 포함하는지 확인하여 결과를 결정한다.
!~는 ~와 반대로 포함하지 않는 경우 true를 반환한다.

awk program 실행 방법
마지막으로 작성한 awk program을 어떻게 수행하는지 알아보도록 하자.
수행 방법은 다음과 같다.

awk -f script_filename input_filename
혹은
awk 'script' input_filename

위의 방법은 awk script(program)을 다른 파일로 저장하였을 때(프로그램이 길때) 사용하는 방법이고,
아래의 방법은 간단한 awk script를 사용할 때 program을 작은 따옴표 안에 적어 사용하는 방법이다.

예를 들어
program을 작성한 파일이 script.awk이고
입력 텍스트가 input.txt라면

awk -f script.awk input.txt

라고 수행해주면 awk program이 수행된다.


또, awk에서는 program 내부에서 변수를 선언해주는 것 이외에도 awk를 실행할 때, command line에서 parameter를 program으로 넘겨주어 program 내부에서 변수처럼 활용할 수 있다.
이러한 경우

awk -f script_filename param1=arg1 param2=arg2 ... input_filename

처럼 수행해 주면된다.


그리고 입력 파일이 여러 개인 경우는 다음과 같이 실행하면 여러 개의 입력에 대해서 프로그램을 수행할 수 있다.

awk -f script_filename param1=arg11 input_filename1 param1=arg12 param2=arg2 input_filename2

이렇게 수행하였을 경우,
awk는 input_filename1과 input_filename2를 차례로 입력 텍스트로 받게되는데,
이때 param1은 input_filename1을 수행할 땐 arg11값을 가지고 수행하고,
input_filename2를 수행할 땐 arg12의 값을 가지고 수행하게 된다.
또 param2의 경우 input_filename2일 때만 arg2로 값을 가지고 수행하게 된다.


마지막으로 awk로 부터 standard input을 받고 싶다면 command line에서 맨 마지막에 "-"를
기술해 주면 standard input을 받게 된다.
예를 들어

awk -f script.awk input.txt -

이렇게 수행하였을 경우,
awk는 script.awk를 program file을 input.txt과 user로부터 standard input을 받아 수행하게 된다.


여기서 기술한 내용을 예를 통해 확인해 보도록 하자.

입력 텍스트
1000
125       Market                 -125.45
126       Hardware Store         -34.95
127       Video Store            -7.45
128       Boot Store             -14.32
129       Gasoline               -16.10
(구분은 tab으로 이루어져 있음.)

맨 윗줄은 초기 자금을 나타내고
그 아랫줄들은 첫 칸은 index, 두번째 칸은 지출장소, 새번째 줄은 지출비용을 나타낸다.
이를 통해 각각 소비 활동을 하였을 때 잔액을 나타내는 awk 프로그램을 짜보면 다음과 같다.

BEGIN {
FS = "\t"
}

NR==1 {
print "Beginning Balance: \t" $1
balance = $1;
}

NF==3 {
print $0;
print balance += $3;
}

각각의 내용을 분석해 보면,
BEGIN{}에서는 field separator를 tab으로 설정해 주었다.

두번째 괄호는 첫번째 record에서만 수행하므로 첫째줄이 들어오면 첫번째 field를 balance라는 variable에 저장한다.

세번째 괄호에서는 첫째줄 이후, field가 총 3개인 record가 나오면 해당 record를 출력한 후, balance라는 variable에 세번째 field의 내용을 더하고 이를 출력한다.

이를 수행한 결과는 다음과 같다.

Beginning Balance:        1000
125       Market             -125.45
874,55
126       Hardware Store     -34.95
839.6
127       Video Store        -7.45
832.15
128       Boot Store         -14.32
817.83
129       Gasoline           -16.10
810.73


<TIP>

여태까지 우리는 print구문을 사용해서 출력을 확인하였는데,
awk에서도 C programming에서 사용하는 printf구문을 지원한다.
그러므로 C programming에 익숙한 사람은 printf구문을 사용하면 정형화된 출력을 하기가 매우 편리하다.

'Linux' 카테고리의 다른 글

[awk] awk 사용법#4 - Array  (0) 2010.05.14
[awk] awk 사용법#3 - Statements  (0) 2010.05.14
[awk] awk 사용법#1 - awk program의 구조  (0) 2010.05.13
[CVS] CVS 사용법  (0) 2010.05.11
[Linux] Linux Command Summary  (0) 2010.04.16
Posted by sunshowers
,