728x90

종종 사용하지만 매일 사용하지 않는 명령이나 옵션들이 많습니다.

금방 기억이 나면 좋으련만 나이가 들어가는지 매번 구글의 도움을 받게 되네요.

겸사겸사 블로그에 기록해 두고 저와 비슷한 기억력 감퇴를 겪는 분들에게

일말의 도움을 주고자 이렇게 시간을 할애해 봅니다. (훗)

 

 


리눅스나 맥 환경에서 grep 은 정말 유용한 명령입니다.

텍스트 파일에서 필요한 내용을 찾아내는데 도사이기 때문이죠.

간단한 사용법은 cat 등으로 텍스트 파일을 읽고

파이프로 grep 을 연결해서 필요한 필터 조건을 거는 방법입니다. 

 

// "NoPD" 가 들어간 행을 찾습니다
$ cat test.txt | grep NoPD

 

만약 대량의 로그파일에서 필요한 내용을 찾으려면 어떻게 해야 할까요?

단순한 웹 엑세스 로그라면 위와 같은 방법에 한번 더 파이프로 awk 를 연결하면 되겠습니다만 

Java 의 trace 로그라던가 debug 성격의 로그라면 

에러 문자열 앞뒤에 있는 여러 행을 또 찾아야 합니다.

 

이럴때 써먹을 수 있는 grep 의 좋은 옵션이 있었으니

After 를 상징하는 -A 와 Before 를 나타내는 -B 옵션이 우리의 구세주입니다. 

아래와 같은 파일이 있다고 해보겠습니다. 

 

$ cat test.txt
03/23	1
03/23	2
03/23	3
03/23	4
03/23	separator
03/23	5
03/23	6
03/23	7
03/23	8

 

우리는 separator 라는 문자를 찾도록 grep 을 이용할 겁니다.

그리고 여기에 -A 와 -B 옵션을 이용해서

separator 문자열 앞 뒤의 행들을 같이 결과로 출력해 보겠습니다. 

 

// separator 문자열이 포함된 행 바로 뒤(After)의 4개 행을 출력합니다. 
$ cat test.txt | grep -A 4 separator
03/23	separator
03/23	5
03/23	6
03/23	7
03/23	8

// separator 문자열이 포함된 행 바로 직전(Before)의 4개 행을 출력합니다.
$ cat test.txt | grep -B 4 separator
03/23	1
03/23	2
03/23	3
03/23	4
03/23	separator

 

네, 참 쉽고 편리합니다.

만약 separator 가 여러개 있다면 어떻게 될까요?

 

// separator 가 여러 행에 존재하는 파일
$ cat test.txt
03/23	1
03/23	2
03/23	3
03/23	4
03/23	separator
03/23	5
03/23	6
03/23	7
03/23	8
03/24	separator
03/24	9
03/24	10
03/24	11
03/24	12

// 모든 separator 를 찾아 이후(After) 4개의 행을 출력합니다. 친절하게 -- 로 행 나눔까지...
$ cat test.txt | grep -A 4 separator
03/23	separator
03/23	5
03/23	6
03/23	7
03/23	8
--
03/24	separator
03/24	9
03/24	10
03/24	11
03/24	12

// 모든 separator 를 찾아 이전(Before) 4개의 행을 출력합니다. 역시... 친절합니다. 
$ cat test.txt | grep -B 4 separator
03/23	1
03/23	2
03/23	3
03/23	4
03/23	separator
--
03/23	5
03/23	6
03/23	7
03/23	8
03/24	separator


알아서 척척척 일을 잘 해줍니다.

before, after... 로 grep 의 -B, -A 옵션을 기억합시다!!

728x90
728x90

터미널에서 로그파일을 핸들링하면서 자주쓰이는 명령들이 있습니다. 전체 파일을 출력하기 위해서 cat 명령을 사용하고 특정한 컬럼의 값만 출력하기 위해서 파이프로 연결된 awk 명령을 쓸 때가 많습니다. 그런데, 컬럼이 아주 많은 경우에 특정한 컬럼만 제외하고 나머지를 출력할 수 있는 방법이 있을까요? 컬럼이 적은 경우에는 필요한 필드를 나열하는 것도 괜찮지만, 수십개, 수백개의 컬럼이 있다면 그다지 좋은 방법이 될 수가 없습니다.


예를 들어 temp.txt 파일에 아래와 같이 스페이스로 구분된 10개의 컬럼이 있다고 해보겠습니다. 이 파일의 정보들 중에서 특정한 컬럼의 값만 추출하고 싶다면 awk 명령을 이용해서 print 예약어를 이용할 수 있을 겁니다. 


$ cat temp.txt

C1 C2 C3 C4 C5 C6 C7 C8 C9 C10

$ cat temp.txt | awk '{print $3, $5}'

C3 C5


이 데이터 파일에서 거꾸로 3번 컬럼과 5번 컬럼의 값을 제외한 나머지 컬럼의 값을 추출하려면 어떻게 해야 할까요? print 구문의 파라메터로 $3 과 $5 만 빼고 나열해도 되겠지만, 아래와 같이 명령을 입력하면 훨씬 빠르고 쉽게 특정한 컬럼만을 제외하고 데이터를 정제할 수 있게 됩니다.


$ cat temp.txt | awk '{$3=$5=""; print $0}'

C1 C2  C4  C6 C7 C8 C9 C10


동일한 결과물을 얻어내는 방법이 여러가지 있다면 그중에서 가장 간편한 방법을 택하는 것이 누가 뭐라해도 진리일 겁니다. 작업시간을 절약하고 더 집중해야 하는 것들에 몰입하는 하루 되시길 바랍니다!



728x90
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

+ Recent posts