pattern scanning and processing language

bash 상에서 간단히 문자열을 파싱할 때 사용할 수 있는 프로그램이다. 그게 과연 간단한지 아닌지는 사용법을 좀 보고 익숙해지면 나름 판단되겠지만.

기본 사용법

예를 들어 md5sum 프로그램을 실행했다고 가정하자. 보통 아웃풋이 이렇게 나온다.

$ echo "hashme" | md5sum
12adcdee8dd3155fd1108a4ed1892d6d  -

필요로 하는 문자열은 앞의 해시 필드이고 뒤의 네임 필드는 필요가 없다. 따라서 이 부분을 없앤 값만을 받고 싶은데 이런 경우 어떻게 해결할 수 있냐는 것이다. 문자열만을 파싱한다면 당연히 파이썬이나 루비 등의 자신있는 프로그램을 사용하면 되지만 bash에서 사용하긴 어렵다. 바로 이럴 때, awk를 사용할 수 있다.

$ echo "hashme" | md5sum | awk '{print $1}'
12adcdee8dd3155fd1108a4ed1892d6d

AWK의 옵션

파싱 문자 변경하기, -F

field-separator fs를 변경한다. 윕력하지 않으면 자동으로 미리 설정된 FS를 사용한다. 위 경우에는 공백이 된다. 만약 csv라면 fs ,를 사용하면 되겠다.

$ echo "hello,world" | awk -F ',' '{print $1}'
hello
$ echo "hello,world" | awk -F ',' '{print $2}'
world

AWK 내장 함수

라인 스킵, NR/FNR

도커 컨테이너들의 정보를 awk를 이용해서 파싱한다고 치자. 얻고 싶은 정보는 도커 컨테이너의 아이디라고 했을 때(사실 docker ps -a -q볼 수 있다), 첫 라인이 같이 출력된다는 점이다.

CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS                    PORTS               NAMES
b0202ee2051a        ubuntu                         "/bin/bash"              11 hours ago        Exited (1) 11 hours ago                       evil_lichterman
3487fd2d0229        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   thirsty_northcutt
bd2198083934        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   stupefied_brattain
27f20047c36f        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   pedantic_pare
1cec4989b5f7        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   backstabbing_morse
b914bbbd1164        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   high_booth
a5f454b3c489        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   compassionate_feynman
319585b4c162        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   nostalgic_montalcini
e07ce8d3c82b        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   cocky_perlman
701bf725d5ab        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   hopeful_lichterman
386b4294fb46        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   angry_brattain
5c0f7dea4d5b        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   hungry_payne
1cc2a0c119fb        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   cocky_yonath
b35bda29a786        cublr/armhf-alpine-basic   "/bin/sh"                11 hours ago        Up 11 hours                                   thirsty_goldberg
$ sudo docker ps -a | awk '{print $1}'
CONTAINER
71a55d463a60
9c671a144c90
401a78d2109f
df01fa293373
03ca1226b873
7843d6fb8794
9c388350eeb4
d81191ab2590
c963d26674a7
39e4283a6b85
c1cfbf92680f

첫 라인을 스킵해야 하는 경우에는 내장 함수 NR/FNR을 사용할 수 있다.

$ sudo docker ps -a | awk 'NR > 1 {print $1}'
71a55d463a60
9c671a144c90
401a78d2109f
df01fa293373
03ca1226b873
7843d6fb8794
9c388350eeb4
d81191ab2590
c963d26674a7
39e4283a6b85
c1cfbf92680f

$ sudo docker ps -a | awk 'FNR > 1 {print $1}'
71a55d463a60
9c671a144c90
401a78d2109f
df01fa293373
03ca1226b873
7843d6fb8794
9c388350eeb4
d81191ab2590
c963d26674a7
39e4283a6b85
c1cfbf92680f

만약 여러 파일을 awk에서 사용해야 할 경우는 NR대신에 FNR을 사용하자.