728x90

다량의 데이터를 추출하면 필연적으로 정렬에 대한 필요성이 생깁니다. 정렬이 필요한 순간은 정말 다양하겠지만 대표적인 경우들을 들어보자면, 1) 특정한 조건에 만족하는 로그 라인의 갯수를 오름/내림 차순으로 정렬, 2) 시계열 순으로 로그가 추출되지 않은 경우, 시간 컬럼을 기준으로 로그 라인을 정렬과 같은 것이 있습니다. 1의 경우는 카운트를 위한 명령을 파이프로 연결후 쉽게 정렬할 수 있습니다.


$ cat domain.log | awk '{print $3}' | sort


위의 커맨드는 domain.log 파일을 핸들링하면서 세번째 열을 출력하고 이를 정렬하는 명령어 입니다. 여기에 파이프를 추가하여 유니크(Unique)한 이름을 발라내고, 다시 카운트된 갯수를 기준으로 정렬하려면 아래와 같은 명령을 생각할 수 있습니다.


$ cat domain.log | awk '{print $3}' | sort | uniq -c | sort -rn


그런데 특정한 컬럼을 기준으로 정렬하되 전체 데이터를 유지하려면 awk 명령으로는 왠지 좀 불편한 느낌입니다. 이때는 awk 를 이용하지 말고 sort 명령만으로 정렬하는 것이 더 유리합니다. 


$ cat domain.log | sort -k 3


이렇게 하면, 세번째 컬럼 (이때는 공백으로 각 컬럼이 나뉘어진 데이터라 가정했습니다) 을 기준으로 정렬후 데이터를 출력해 주게 됩니다. 자주 쓰는 명령인데 쓸때마다 자꾸 구글링하게 되어 블로그에 기록해 둡니다!



728x90
728x90

터미널에서 대량의 로그 데이터를 다루는데 무척 유용한 명령이 awk 입니다. awk 는 기본적으로 파일 내의 컬럼 구분자가 공백이라는 가정하게 동작합니다. 데이터를 추출하려는 원본 로그 파일이 공백을 구분자로 이용하는 경우 문제가 없지만 CSV (Comma Seperated Value) 형태 혹은 파이프와 같은 구분자로 컬럼을 식별하는 경우에는 구분자가 어떤 문자인지 awk 에게 전달해 주어야 합니다.


[ 예시 로그 파일 ]

$ cat domain.log

2016-03-28, 09:00:00, www.samsung.com

2016-03-28, 09:00:00, www.naver.com

2016-03-28, 09:00:00, www.apple.com

...


위와 같이 사용자들이 접근한 도메인에 대한 이력을 정리한 로그파일이 있다고 가정해 보겠습니다. 각 도메인별로 사용자의 요청 횟수를 카운트 하고 싶다면 아래와 같은 명령이 머릿속에 떠오르실 겁니다. 


$ cat domain.log | awk '{print $3}' | sort | uniq -c | sort -rn


하지만 위의 명령은 awk 의 기본 구분자인 공백을 사용하기 때문에 원하는 결과가 제대로 나오지 않게 됩니다. 로그 파일이 콤마를 명시적인 구분자로 사용하고 있기 때문에 아래와 같이 awk 의 파라메터로 구분자를 알려주어야 합니다. 


$ cat domain.log | awk -F ',' '{print $4}' | sort | uniq -c | sort -rn


자주 사용하지만 자꾸만 잊어버리는 명령어들 시리즈였습니다 ;-)


728x90
728x90

터미널에서 다량의 로그, 텍스트 파일을 핸들링 할때 awk 명령을 파이프로 연결하여 작업하는 경우가 많습니다. 예를 들어 텍스트 파일의 첫번째 컬럼이 "A" 인 행의 세번째 필드를 출력하는 방법은 대략 아래와 같을겁니다.


$ cat sample.txt | awk '$1=="A" {print $3}'


그런데 가끔은 특정한 조건을 만족하는 행의 모든 내용을 출력하고 싶을 때가 있습니다. 컬럼이 몇 개 안된다고 하면 print 명령으로 모든 컬럼을 지정하면 되겠지만 컬럼이 많다면 쉽지 않습니다. 이때는 print 의 파라메터로 $0 을 넘기면 모든 컬럼이 출력되게 됩니다.


$ cat sample.txt | awk '$1=="A" {print $0}'


자주 사용하지 않으면 잊어버리기 때문에 기억을 위해 남겨둡니다.


- NoPD -

728x90

+ Recent posts