리눅스 awk 사용법


awk

  • awk : 데이터를 조작하고 리포트를 생성하기 위해 사용하는 언어입니다. 리눅스에서 사용하는 awk는 GNU 버전의 gawk로 심볼릭 링크되어 있습니다
  • 간단한 연산자를 명령라인에서 사용할 수 있으며, 큰 프로그램을 위해 사용될 수 있습니다. awk는 데이터를 조작할 수 있기 때문에 쉘 스크립트에서 사용되는 필수 툴이며, 작은 데이터베이스를 관리하기 위해서도 필수입니다
  • Alfred Aho, Peter Weinberger, Brian Kernighan 3명이 만들었는데 이들의 이름 이니셜을 가져와서 awk라고 부릅니다

awk 프로그래밍 형식

  • awk 명령어를 입력한 다음, 작은따옴표로 둘러싸인 패턴이나 액션을 입력하고 마지막엔 입력 파일 이름. 파일 이름을 지정하지 않으면 키보드 입력에 의한 표준 입력을 받음. 그리고 awk는 입력된 라인들의 데이터들을 공백 또는 탭을 기준으로 분리해 $1부터 시작하는 각각의 필드 변수로 분리해 인식

  • awk 형식

    awk 'pattern' filename
    awk '{action}' filename
    awk 'pattern {action}' filename
    
  • 예시

    $ vi awkfile  
    홍 길동 3324    5/11/96 50354  
    임 꺽정 5246    15/9/66 287650  
    이 성계 7654    6/20/58 60000  
    정 약용 8683    9/40/48 365000 
    
    $ awk '{print $0}' awkfile
    > 
    홍 길동 3324    5/11/96 50354  
    임 꺽정 5246    15/9/66 287650  
    이 성계 7654    6/20/58 60000  
    정 약용 8683    9/40/48 365000 
    
    $ awk '{print $1}' awkfile
    > 
    홍
    임
    이
    정
    
    $ awk '/길동/' awkfile
    > 홍 길동	3324	5/11/96	50354
    
    $ awk '/정/{print "\t안녕하세요? " $1, $2 "님!"}' awkfile
    > 
      안녕하세요? 임 꺽정님!  
      안녕하세요? 정 약용님!
    
    $ awk '/홍/{print $1, $3}' awkfile
    > 홍 3324
    
    $ df | awk '$4 < 100000' : |을 이용해 파이프라인 생성
    >
    devfs			368       368       0   100%     638          0  100%   /dev
    map -hosts	0         0         0   100%       0          0  100%   /net
    map auto_home	0         0         0   100%       0          0  100%   /home
    
  • awk 동작원리
    1. awk는 파일 또는 파이프를 통해 입력 라인을 얻어와 $0라는 내부 변수에 라인을 입력. 각 라인은 레코드라고 부르고, newline에 의해 구분
    2. 라인은 공백을 기준으로 각각의 필드나 단어로 나뉜다. 필드는 $1부터 시작. 많게는 100개 이상의 필드를 저장할 수 있음
    3. 내장 변수인 FS라고 부르는 필드 분리자가 공백을 할당받는다. 필드가 콜론이나 대시와 같은 문자에 의해 분리되면 새로운 필드 분리자로 FS의 값을 변경할 수 있다
    4. awk는 화면에 필드를 출력할 때 print 함수를 사용
    5. 콤마는 출력필즈 분리자(OFS)와 매핑되어 있으며 공백을 할당받음
  • OFMT 변수
    • 숫자를 출력할 때 숫자 포맷 제어할 경우 사용. 간단히 printf를 사용할 수도 있지만, OFMT를 지정할 수 있음.
    • default는 %.6g로 소수점 6자리
      $ awk 'BEGIN{OFMT="%.2f"; print 1.23412, 15E-3}'
      > 1.23 0.01
      
  • printf 함수
    • 포매팅된 깔끔한 출력을 할 경우 사용
    • newline을 제공하지 않기 때문에 newline이 요구되면 \n을 사용해야함
    • c : 문자, d : 10진수, f : 실수, x : 16진수
    • -이 붙으면 좌츠겡서 시작되고 기본형이면 우측에서 시작
      $ awk '{printf "The name is %-20s Number is %4d\n", $1" "$2, $3}' awkfile  
      > 
      The name is 홍 길동           Number is 3324
      The name is 임 꺽정           Number is 5246
      The name is 이 성계           Number is 7654
      The name is 정 약용           Number is 8683
      
  • awk -f 옵션
    • awk 액션과 명령이 파일에 작성되어 있다면 -f 옵션을 사용
      awk -f [awk 명령파일] [awk 명령을 적용할 텍스트 파일]
    
      $ vi awkcommand 
      {print "안녕하세요 " $1, $2"님"}
      {print $1, $2, $3, $4, $5}
    
      $ awk -f awkcommand awkfile
      > 
      안녕하세요 홍 길동님
      홍 길동 3324 5/11/96 50354
      안녕하세요 임 꺽정님
      임 꺽정 5246 15/9/66 287650
      안녕하세요 이 성계님
      이 성계 7654 6/20/58 60000
      안녕하세요 정 약용님
      정 약용 8683 9/40/48 365000
    
  • 레코드와 필드
    • 레코드
      • awk는 입력 데이터를 볼 수 없지만 포맷 또는 구조는 볼 수 있다. 레코드라고 불리는 각 라인은 newline으로 분리
      • NR 변수 : 각 레코드들의 번호는 awk의 빌트인 변수 NR에 저장된다. 레코드가 저장된 다음 NR의 값은 하나씩 증가한다
        $ awk '{print NR, $0}' awkfile
        > 
        1 홍 길동	3324	5/11/96	50354
        2 임 꺽정	5246	15/9/66	287650
        3 이 성계	7654	6/20/58	60000
        4 정 약용	8683	9/40/48	365000
      
    • 필드
      • 각 레코드는 디폴트로 공백이나 탭으로 분리된 필드라는 워드로 구성된다. NF에 필드의 수를 유지하며 라인당 100개의 필드를 가질 수 있다
        $ awk '{print $1, $2, $5,  NF}' awkfile
        > 
        홍 길동 50354 5
        임 꺽정 287650 5
        이 성계 60000 5
        정 약용 365000 5
      
    • 필드 분리자
      • 빌트인 변수 FS는 입력 필드 분리자의 값을 가지고 있음. default는 공백과 탭. FS 값을 변경하기 위해선 -F을 사용하며 -F 다음에 오는 문자가 새로운 필드 분리자가 됨

          $ vi awkfile_FS
          홍 길동 :3324   :5/11/96        :50354
          임 꺽정 :5246   :15/9/66        :283502
        
          $ awk -F: '/홍/{print $1, $2}' awkfile_FS
          > 홍 길동	 3324
        
          $ awk -F'[ :\t]' '/홍/{print $1, $2}' awkfile_FS
          > 홍 길동
        

awk와 정규표현식

  • 정규표현식은 슬래시로 둘러싸인 문자들로 구성된 패턴

      $ awk '/^정/{print $1, $2, $3}' awkfile
      > 정 약용 8683
    
      $ awk '/^[A-Z][a-z]+ /' awkfile2
      > Hong KilgDong	3324	5/11/96	50354
    
  • match 연산자(~) : 표현식과 매칭되는 것이 있는지 검사하는 연산자

      $ awk '$2 !~ /g$/' awkfile2 : 2번 필드가 g로 끝나지 않는 라인 출력
      > Lee Seongkye	7654	6/20/58	60000
    
  • POSIX 문자 클래스

      $ awk '/[[:lower:]]+g[[:space:]]+[[:digit:]]' awkfile2 
      > Hong KilgDong	3324	5/11/96	50354
    

    비교 표현식

  • 어떤 상태가 참일때만 액션이 수행

      $ awk '$3 > 7000{print $1, $2}' awkfile
      > 
      이 성계
      정 약용
    
  • 조건 표현식
    • 표현식을 검사하기 위해 ?:를 사용. if/else가 하는 역할과 같은 결과를 의미
      $ awk '{max={$1 > $2) ? $1 : $2; print max}' filename
      if $1 > $2:
          max = $1
      else:
          max = $2
    
  • 산술 연산자
    • 계산을 통해 필터링 가능
  • 논리 연산자
    • && : AND 연산
    • || : OR 연산
    • ! : NOT 연산
      $ awk '$3 > $5 && $3 <= 100' filename
    

awk 변수

  • BEGIN 패턴
    • awk가 입력 파일의 라인들을 처리하기 이전에 실행되며 액션 블록 앞에 놓임
    • 입력 파일 없이 테스트할 수 있고, 빌트인 내장 변수(OFS, RS, FS)들의 값을 변경할 경우 사용
  • END 패턴
    • 어떤 입력 라인과도 매칭되지 않고, 입력 모든 라인이 처리된 후 실행됨
    • BEGIN만 사용할 경우엔 아규먼트 파일명을 적지 않아도 되지만 END 블록을 사용할 경우엔 반드시 아규먼트 파일을 적어야 함
      $ awk '/Tom/{count++}END{print "Tom was found " count " times."}' awkfile5
    

awk 리다이렉션

  • awk결과를 리눅스 파일로 리다이렉션할 경우 쉘 리다이렉션 연산자를 사용
  • 파일명은 큰따옴표로 둘러쌰아 함
  • > 심볼이 사용될 때 파일이 오픈되고 잘려짐

      $ awk -F: '$4 >= 60000 {print $1, $2 > "new_file"}' awkfile5
    
  • getline 함수
    • 표준 입력, 파이프, 현재 처리되고 있는 파일로부터 입력을 읽기 위해 사용. 입력의 다음 라인을 가져와 NF, NR, FNR 빌트인 변수를 설정
    • 레코드가 검색되면 1을 리턴하고, 파일의 끝이면 0을 리턴. 에러가 발생하면 -1을 리턴

        $ awk 'BEGIN{ "date " | getline d; split(d, year) ; print year[6]}'
        > 2009
      
        $ awk 'BEGIN{while (getline < "/etc/passwd" > 0)lc++; print lc}' filename
      
  • awk 파이프
    • awk 프로그램에서 파이프를 오픈하고 또다른 파이프를 오픈하기 전에 기존 파이프는 닫아주어야 한다. 파이프 심볼의 오른쪽 명령은 큰따옴표(““)로 둘러싸야 한다

        $ awk '{print $1, $2 | "sort-r"}' cars
      
    • END블록에 close를 사용해 파이프를 꼭 닫아줘야 함

        $ awk '{print $1, $2 | "sort -r"} END{close("sort -r")}' cars
      

카일스쿨 유튜브 채널을 만들었습니다. 데이터 사이언스, 성장, 리더십, BigQuery 등을 이야기할 예정이니, 관심 있으시면 구독 부탁드립니다 :)

PM을 위한 데이터 리터러시 강의를 만들었습니다. 문제 정의, 지표, 실험 설계, 문화 만들기, 로그 설계, 회고 등을 담은 강의입니다

이 글이 도움이 되셨거나 다양한 의견이 있다면 댓글 부탁드립니다 :)

Buy me a coffeeBuy me a coffee





© 2017. by Seongyun Byeon

Powered by zzsza