Raspberry Pi_Kor_10.9.1 “awk” 명령


Published Book on Amazon


All of IOT

Starting with the Latest Raspberry Pi from Beginner to Advanced – Volume 1

All of IOT

Starting with the Latest Raspberry Pi from Beginner to Advanced – Volume 2


출판된 한글판 도서


최신 라즈베리파이(Raspberry Pi)로 시작하는 사

물인터넷(IOT)의 모든 것 – 초보에서 고급까지 (상)

최신 라즈베리파이(Raspberry Pi)로 시작하는 사

물인터넷(IOT)의 모든 것 – 초보에서 고급까지 (하)


Original Book Contents


10.9   자료 조작 관련 명령

 

10.9.1  "awk" 명령

 

"awk" 명령어는 지정된 파일을 읽어 지정된 패턴과 일치하는 값을 가지고 있는 행을 찾고, 패턴이 일치하면 지정된 연산작업을 수행한다. 여기서의 연산은 라인 내의 필드 조작이나 필드 값을 이용한 산술 연산을 의미한다.  "awk"라는 이름은 이를 개발한 세 사람의 이름 Aho, Weinberger, Kernighan에서 유래된 것이다.

 

"awk" Shell 프로그래밍과 BC, C 프로그래밍 언어와 같은 기능을 갖춘 프로그래밍 언어로 BC와 같이 완벽하게 작동하며 Shell의 인수인 $1, $2, $3과 같은 이름을 가진 필드 변수가 각 입력 라인에 사용될 수 있다. C 언어와 유사한 프린팅, 제어 연산자도 가지고 있다.

 

[명령 형식]

awk   program    <directory/파일>

 

[명령 개요]

    지정된 파일에서 지정된 패턴과 일치하는 값을 가진 행을 찾고, 패턴이 일치하는 행이 있으면 지정 작업을 수행한다.

    user 권한    -- 일반 user.

 

[상세 설명]

   "awk" 입력 라인을 읽는 방법

 

표준 입력이나 파일에서 자료를 읽을 때 각 라인을 공백문자를 기준으로 여러 개의 필드로 나눈다. 이 명령에서는 필드를 나타내는 변수를 사용할 수 있다. $1은 첫 번째 필드이고 $2은 두 번째 필드이다. $0은 전체 라인을 나타낸다.

 

공백문자 대신에 다른 구분자를 사용하고자 하면 "-F" (field) option으로 임의의 문자를 지정하여 필드 구분자로 사용할 수 있다. 예를 들어 ":" (콜론)을 구분자로 사용하려면 다음과 같이 입력한다.

    awk  -F:   program    data-files


 

   program

 

명령에서 읽어 들이는 라인과 필드들에 대한 작업을 program으로 표현한다. program은 하나 또는 그 이상의 program 라인들로 이루어진다.   program 라인은 pattern action의 쌍으로 정의되며 전체적인 형식은 다음과 같다.

    pattern {action}

    pattern {action}

 

아래의 예를 보자. program을 사용하면, 문자열 "rotate"를 포함하고 있는 라인들을 검색하고, 그것들을 프린트한다. 이것은 "grep rotate filename" 명령을 사용하는 것과 동일한 효과를 갖는다.

    /rotate/ {print}   à 패턴은 "rotate"이고, action "print"이다.

 

pattern을 정의할 때 단순한 문자열 패턴은 문자열 앞/뒤를 "/"로 둘러싸는 형태로 정의한다. 다음과 같은 특이한 pattern을 사용할 수도 있다.

    /fish/                 문자열 "fish"를 포함하고 있는 라인

    $1 ~ /fish/            첫 번째 필드가 문자열 "fish"를 포함하고 있는 라인

    $1 !~ /fish/           첫 번째 필드가 문자열 "fish"를 포함하고 있지 않은 라인

 

위에서 "~"는 우측에 있는 패턴이 좌측에 있는 필드에 포함되는 것을 의미한다.  "!~" 조합은 우측의 패턴이 좌측의 필드에 포함되지 않음을 의미한다.

 

action 부분을 중괄호로 둘러쌈으로써 패턴과 구분한다. action 부분이 생략되면 그 라인이 프린트된다. 일반적으로 사용되는 action에는 "print"가 있으며 이 action은 인수를 표준 출력에 출력한다. { } 속에 하나 이상의 action들을 포함시킬 때는 세미콜론으로 분리시킨다.

    {print $2}             두 번째 필드를 프린트하라

    {print $4,$2}          네 번째 필드, 두 번째 필드의 순서로 내용을 프린트하라

    {print $2,$2+$4}       두 번째 필드, 두 번째 필드와 네 번째 필드의 합을 프린트하라

    {s=$2+$4; print s}     두 번째와 네 번째 필드를 합계를 계산하고, 그 합을 프린트하라

 

 


 

   action의 다양한 사례

 

다음에서는 다양한 action 사례를 보여줄 것이다. 기본적으로 {print $2, $1}을 사용하여 설명할 것이다. 아래에서 생성하는 파일은 테스트를 위한 파일이다.

 

pi@raspberrypi ~ $ vi  in.file

hello goodbye again

111 222

thirty forty

 

다음 사례는 입력 필드 두 개의 순서를 바꾸어 출력한다. 이 예에서 "print"의 인수는 콤마로 구분되었으며, 이로 인해 출력 데이터 사이에 현재의 필드 구분자인 공백이 삽입되었다. 콤마가 생략되면 $1 $2가 연속하여 출력된다.

 

pi@raspberrypi ~ $ vi awk.prog1

{print $2, $1}

pi@raspberrypi ~ $ awk -f  awk.prog1  in.file

goodbye hello

222 111

forty thirty

 

다음 사례에서는 "awk" 명령의 program에 대해서 입력화일 내에서 "/hello/" 패턴과 일치하는 라인은 1개뿐이기 때문에 그 라인에 대해서만 지정된 action "print"가 실행된다.

 

pi@raspberrypi ~ $ vi awk.prog2

/hello/ {print $2, $1}

pi@raspberrypi ~ $ awk -f awk.prog2  in.file

goodbye hello

 


 

다음 사례에서는 두 번째 "print" 명령어에서 추가된 parameter가 따옴표로 둘러싸여 있으며, 그 문자열이 기존의 출력에 추가되어 표시된다.

 

pi@raspberrypi ~ $ vi awk.prog3

/hello/ {print $2, $1}

/thirty/ {print $1, $2, "and more"}

pi@raspberrypi ~ $ awk -f awk.prog3  in.file

goodbye hello   

thirty forty and more

 

다음 사례에서 "||" 연산자는 2개의 정규식 중 하나만 일치하면 지정된 연산을 실행하며 "&&" 연산자는 2개의 정규식이 모두 일치해야 지정 연산을 실행한다. "!" 연산자는 정규식이 일치하지 않아야 지정된 연산을 실행하며, 정규식 앞에 기술된다.

 

pi@raspberrypi ~ $ vi awk.prog4

/hello/||/111/  {print "hit", $1, $2}

pi@raspberrypi ~ $ awk -f awk.prog4  in.file

hit hello goodbye          

  hit 111 222

 

다음 사례에서는 패턴 "/hello/"와 일치하는 첫 번째 입력 라인만이 연산의 대상이 된다.

 

pi@raspberrypi ~ $ vi awk.prog6

/hello/ {

           print $2

           print "another"

           print $1

}

pi@raspberrypi ~ $ awk -f awk.prog6  in.file

goodbye

  another

  hello

 


 

   awk 명령 action에서의 숫자 연산

 

"awk"의 산술 연산이 bc의 산술 연산과 다른 점은 "awk"는 입력 파일 내의 라인 중 일부를 선택하는 패턴 기능을 사용할 수 있다는 것이다. 예를 들어 "awk"의 내장 함수인 "length"는 문자열로 취급되는 입력 필드의 길이를 반환하며, 숫자 변수는 숫자로 취급되는 필드의 값을 할당받을 수 있지만, 숫자로 변환될 수 없는 문자열은 값이 "0"이 된다.

 

다음 사례에서 문자열 "goodbye" "thirty"는 숫자로 변환될 수 없으므로 "0"이 할당된다. 그러나 문자열 "222"는 숫자로 올바르게 변환되었다. 또한 "s=0"과 같은 형식으로 변수에 값을 할당할 수 있다.

 

pi@raspberrypi ~ $ vi awk.prog7

{

             s += $2

             print $2, "length=" length($2), "s=" s

       }

pi@raspberrypi ~ $ awk -f awk.prog7  in.file

goodbye length=7 s=0   

  222 length=3 s=222

  forth length=5 s=222     

 


 

   "awk" 명령과 변수

 

"awk"에서는 변수를 사용할 수 있다. 변수는 사용하기 전에 선언하거나 초기화시킬 필요는 없다. "awk"가 자체적으로 변수를 초기화시키며, 필요에 따라 그 변수에 문자열이나 숫자를 기억시킬 수 있다. 다음은 "awk" 변수의 올바른 예이다.

   s,    S,    SS,    S1,    qwerty[42]

 

다음 사례와 같이 자동적으로 변수의 형식이 변환되므로 변수를 쉽게 사용할 수 있다.

 

pi@raspberrypi ~ $ vi awk.prog8

/hello/ {

             SSS=34

             print "SSS is", SSS

             SSS=hello

             print "SSS is", SSS

           }

pi@raspberrypi ~ $ awk -f awk.prog8  in.file

SSS is 34

    SSS is hello

 

[주요 Option]

-f file

 

Program text is read from file instead of from the  Shell.  Multiple -f options are allowed.

file: 프로그램 명령어들을 포함하고 있는 파일의 명칭

-F(field)

 

-F value

sets the field separator, FS, to value.

선택자 뒤에 임의의 문자를 입력하면 필드 구분자가 그 문자로 변경된다.

 


 

[사용 Example]

파일 "sales"는 여섯 열의 정보를 가지고 있다. 처음부터 품목 명칭, 품목의 판매가격, 그리고 품목에 대한 분기별 판매수량이다. 여기서는 "awk" 명령을 이용하여 품목 판매수량 합계와 품목 판매금액 합계를 계산하여 파일에 추가할 것이다. 이를 위해서 다음과 같은 "addup"이라는 파일을 작성한다.

 

pi@raspberrypi ~ $ vi sales

carts      29.99  45  13  55  22

    corks              0.02  30  20  25  93

    doors     49.99  40  15  20  25

    geese     15.00   2   8   1 128

    nighties  50.00  11  23  15  82

pi@raspberrypi ~ $ vi addup

{total=$3+$4+$5+$6;print $0, total, total*$2}

pi@raspberrypi ~ $ awk -f addup sales

carts      29.99  45  13  55  22         135  4040.64

    corks              0.02  30  20  25  93          93     3.36

    doors     49.99  40  15  20  25         100  4999 

    geese     15.00   2   8   1 128         139  2085 

    nighties  50.00  11  23  15  82         131  6550 

 

위의 action ";"에 의해 분리된 두 부분으로 이루어져 있다. 첫 부분은 판매수량를 합하고, 이를 total 변수에 저장한다. 두 번째 부분은 원래의 라인($0)을 출력하고, 그 뒤에 판매수량을 출력하고, 그 다음에는 total*$2를 출력하는데, 이것은 "판매수량 x 두 번째 열 값"을 의미한다.

 


 

Leave a Reply