검색 엔진의 방문이 늘어나고 있군...

Posted
Filed under 쉘 스크립트
참조 원문 : 6 Tricks with awk
관련 글 : awk 기초, awk를 이용한 검색, awk에서 변수 사용

  AWK는 텍스트 기반의 데이터(파일이나 데이터 스트림)를 처리하기 위한 프로그래밍 언어입니다. 주로 문자열 데이터타입, 배열, 정규 표현식을 사용합니다.

  AWK는 본 쉘과 더불어 표준 유닉스 환경에서 사용할 수 있는 스크립트 언어이며 LSB(Linux Standard Base) 사양서에 반듯이 있어야 하는 것으로 규정된 명령어 중 하나입니다.

  비록 AWK가 1줄 프로그래밍을 지원하고 또 대부분 그렇게 사용되지만 하나의 완벽한 프로그램을 짜는 것도 가능합니다.


1. 파일에서 정렬 없이 중복 내용 삭제
  정렬을 하지 않고도 중복된 내용을 찾아 지우고 다른 파일로 리다이렉트하는 방법입니다.
awk '!x[$0]++'
  그리고 아래는 그 예와 결과입니다.
$ echo -e "aaa\nbbb\naaa\naa\nccc\naa"|awk \!'x[$0]++'
aaa
bbb
aa
ccc

2. 특정 파일 그룹의 총 용량 합산
  아래는 디렉토리 내에 모든 파일의 크기를 합산하는 방법입니다.
ls -l | awk '{s = s+$5 }; END { print s }'
  그리고 아래는 현재 디렉토리와 서브디렉토리 내에 있는 .mp3 파일들의 용량을 합산하는 방법입니다.
ls -lR |grep .mp3 | awk '{s = s+$5 }; END { print s }'

3. find 명령어와 연계
  아래는 find로 컴퓨터 내의 모든 .mp3 파일들을 찾아 위에서 본 것과 비슷한 방식으로 용량을 합산하는 방법입니다.
find / -name "*.mp3" -exec ls -l {} \; | awk '{s = s+$5 }; END { print s }'

4. 사용횟수로 기준으로 내림차순으로 정렬하여 히스토리 출력
history | awk '{a[$'`echo "1 2 $HISTTIMEFORMAT" | wc -w`']++}END{for(i in a){print a[i] "\t" i}}' | sort -rn | head

5. AWK 필드 분석
  각 줄마다 번호를 매기고 다시 각 줄의 아래에 해당 줄에 있는 필드마다 번호를 매겨 출력합니다.
awk '{print NR": "$0; for(i=1;i<=NF;++i)print "\t"i": "$i}'

6. 여러 파일의 파일명을 한 번에 변경
  아래는 특정 파일들의 파일명 끝에 '.new'를 붙이는 방법입니다. 앞 부분의 'ls -al pattern'을 변경하여 다양한 활용이 가능합니다.
ls -1 pattern | awk '{print "mv "$1" "$1".new"}' | sh
2011/01/19 10:27 2011/01/19 10:27
Posted
Filed under 쉘 스크립트
참조 원문 : Using Variables With awk
관련 글 : awk 기초, awk를 이용한 검색, 6가지 awk 트릭

  awk는 내장된 변수와 유저 정의 변수를 지원하며 bash 스크립트 같은 것과 달리 사용하기 전에 미리 선언할 필요가 없습니다. 변수의 종류로는 다음의 3가지가 있습니다.
  1. 시스템 변수(=내장 변수)
  2. 일반(Scalar) 변수
  3. 배열 변수

1. 시스템 변수
  시스템 변수는 대문자로 되어 있으므로 대소문자를 주의하여 사용해야 합니다.

NR: 줄 번호(number of input lines)
  NR 변수는 매 레코드를 읽을 때마다 값이 1씩 증가하는 변수입니다.
$ awk '{print NR}' processes
1
2
3
...생략...
72
73
74

NF: 필드 번호(number of fields)
  각 레코드에는 공백 문자로 구분되는 필드들이 있습니다. 필드의 개수는 레코드에 따라 다를 수 있습니다.
$ awk '{print NF}' processes
11
12
  아래는 각 레코드마다 1,2번째 필드의 내용과 총 필드의 개수를 출력하는 예입니다.
$ awk '{print $1,$2,NF}' /var/log/messages.1
Jul 24 14
Jul 24 11
Jul 24 8
Jul 24 12

FILENAME: 입력 파일 이름(name of input file)
  현재 처리 중인 파일의 이름이 담겨 있습니다. 이 변수는 BODY 섹션 이전에는 선언되지 않기 때문에 BEGIN 섹션에서는 사용할 수 없습니다.

FNR: 입력 파일들 중 현재 사용 중인 파일(used with multiple input files)
  NR과 마찬가지로 줄(레코드)번호를 뜻하지만 NR이 모든 입력 스트림을 통틀어 계산한 줄번호를 출력하는 것과 달리 FNR은 현재 처리 중인 파일 내의 줄번호를 출력합니다.

FS: 필드 구분 문자(field separator character)
  기본적으로 필드는 공백이나 탭으로 구분하지만 "-F" 옵션 뒤에 문자를 적어 해당 문자를 필드 구분 문자로 사용할 수 있습니다. 아래는 ':' 문자로 필드를 구분하는 /etc/passwd 파일에서 'jane'이라는 문자열을 찾아 첫 번째 필드와 네 번째 필드를 출력하는 예입니다.
$ tail /etc/passwd | awk -F: '/jane/{print $1, "Group: "$4}'
jane Group: 502
구분 문자를 여러 개 사용하고 싶다면 정규식을 사용하여 목적을 달성할 수 있습니다. 아래는 공백, 콜론, 탭을 구분 문자로 사용한 모습입니다. 참고로 이스케이프 문자가 하나 있으므로(\t) 싱글 쿼트가 필요합니다.
$ tail /etc/passwd | awk -F'[ :\t]' '/jane/{print $1, "Group: "$4}'

OFS: 출력용 필드 구분 문자(output field separator)
  출력에 사용하는 필드 구분 문자는 기본적으로 공백입니다. 아래처럼 각 필드 사이에 콤마를 사용하면 출력용 필드 구분 문자인 공백이 출력됩니다.
$ tail /etc/passwd | awk -F'[ :\t]' '/jane/{print $1,$2,$3,$4,$6,$7}'
jane x 502 502 /home/jane /bin/bash
  만약 콤마를 쓰지 않는다면 아래처럼 더덕더덕 붙여서 나옵니다.
$ tail /etc/passwd | awk -F'[ :\t]' '/jane/{print $1$2$3$4$6$7}'
janex502502/home/jane/bin/bash

ORS: 출력용 레코드 구분 문자(output record separator)
  각 줄은 하나의 레코드로 취급하며 각 줄의 끝마다 레코드가 끝나는 것으로 취급합니다. 레코드 구분 문자(줄 구분 문자)는 줄 바꿈(new line)을 기본으로 사용합니다.

OFMT: 숫자 출력을 위한 서식(format for numeric output)
  이 변수를 통해 숫자의 서식을 제어할 수 있습니다. 기본 서식은 "%.6g"로 소수점 이하 6자리 수까지 표시합니다.

RS: 레코드 구분 문자(record separator)
  기본적으로 레코드 구분 문자는 줄 바꿈(new line)이다.

$0 변수
  파일 전체를 의미합니다.
$ awk '{print $0}' processes
USER       PID %CPU %MEM    VSZ RSS TTY STAT START TIME COMMAND
root         1  0.0  0.1  10348 720 ?   Ss   22:01 0:01 init [3]
root         2  0.0  0.0      0   0 ?   S<   22:01 0:00 [migration/0]
root         3  0.0  0.0      0   0 ?   SN   22:01 0:00 [ksoftirqd/0]
root         4  0.0  0.0      0   0 ?   S<   22:01 0:00 [watchdog/0]

2. 일반 변수
  숫자나 문자를 담는 변수입니다.
var=3 또는 var="test_string"

3. 배열 변수
  변수의 이름과 함께 숫자가 있는 대괄호의 조합으로 사용합니다.
variable_name[0]
variable_name[1]
2010/12/10 10:33 2010/12/10 10:33
Posted
Filed under 쉘 스크립트
참조 원문 : How To Search Using The Awk Utility
관련 글 : awk 기초, awk에서 변수 사용, 6가지 awk 트릭

  사실 검색만 놓고 따져보면 awk는 grep과 비교해 그리 큰 메리트가 없습니다만 awk의 본래 목적은 검색이 아니라 검색한 내용의 일부를 추출하는 것이기 때문에 awk를 사용하려면 검색 방법을 알아야 할 필요가 있습니다. 아래는 awk의 기본 문법입니다.
awk <search pattern> {<program actions>}
  awk로 검색을 할 때는 아래처럼 두 슬래시(/) 사이에 검색할 문자열을 넣습니다. 참고로 문자열에서 대소문자를 구분합니다.
/Debian/
  아래의 두 명령어는 같은 결과를 출력하는데 그 이유는 검색의 기본 기능은 화면에 대한 출력이기 때문입니다.
awk '/Debian/'
awk '/Debian/' {print}
  만약 "debian"과 "Debian"을 모두 검색하고 싶다면 아래처럼 정규식을 사용할 수 있습니다.
/[Dd]ebian/
  줄의 시작 부분을 검색하려면 "^" 문자를, 끝 부분을 검색하려면 "$" 문자를 사용합니다.
/^Debian/
/Debian$/
  아래는 d부터 m까지 소문자를 검색하는 경우입니다.
/[d-m]/
  다음 숫자를 검색하는 경우입니다.
/[0-9]/
  두 문자열 중 하나라도 일치하는 것이 있는 줄을 검색할 때는 파이파(|) 문자를 두 문자열 사이에 넣습니다. 그리고 이렇게 파이프(|)처럼 쉘이 해석하는 문자가 포함된 경우에는 쉘이 문자열을 맘대로 해석하지 않고 awk에게 온전히 넘겨주게 하기 위해 싱글 쿼트(')를 사용합니다. 사실 아래의 문자열에는 달러($), 백 쿼트(`), 이스케이프(\ 로 시작) 문자가 없기 때문에 더블 쿼트(")를 써도 같은 결과를 얻을 수 있지만 습관을 위해 awk에서는 싱글 쿼트를 쓰는 것이 좋다고 할 수 있겠습니다. 왜 싱글 쿼트(또는 아래의 경우 더블 쿼트도 포함)를 써야 하는지에 대한 자세한 정보는 이 포스트를 참고하시기 바랍니다.
awk '/Iceweasel|Epiphany/' access_log
  파일의 첫 번째 필드를 검색하려면 "$1"로 첫 번째 필드를 검색할 것임을 지정하고 "~" 문자로 해당 필드에서 문자열을 검색할 것임을 알립니다.
awk '$1 ~ /^192.168.5.103$/' access_log
  반대로 위의 상황에서 특정 문자열을 검색 결과에서 제외하려면 아래처럼 느낌표(!) 문자를 사용합니다.
awk '$1 !~ /^192.168.5.103$/' access_log
  아래는 'Debian'이라는 문자열이 있는 줄을 검색한 후 각 줄의 1번째와 20번째 필드를 출력하는 방법입니다.
awk '/Debian/' access_log | awk '{print $1,$20}'
  아래는 연속된 여러 줄을 출력하는 방법입니다.
awk 'NR == 10,NR == 15' access_log
  그리고 아래는 사용할 수 있는 연산자입니다.
<           미만
<=          이하
==          일치
!=          불일치
>=          이상
>           초과
  또한 AND 연산을 위한 &&와 OR 연산을 위한 ||도 사용이 가능합니다. 아래는 이를 이용하여 10번째 이상의 줄에서 첫 번째 필드가 두 IP 중 하나인 줄을 찾는 내용입니다.
awk '((NR >= 10) && ($1 == “192.168.5.103″)) || ($1 ==”192.168.5.104″)' access_log
  문자열 안에 넣을 수 있는 이스케이프 문자들은 아래와 같습니다.
\n     줄 바꿈 (라인 피드)
\t     수평 탭
\b     백스페이스
\r     캐리지 리턴
\f     폼 피드
2010/12/09 16:28 2010/12/09 16:28
Posted
Filed under 쉘 스크립트
참조 원문 : Introduction to awk
관련 글 : awk를 이용한 검색, awk에서 변수 사용, 6가지 awk 트릭

  awk는 패턴을 찾아 그와 관련된 문자열을 처리하는 유틸리티로 텍스트 파일에서 정보를 찾아 필요한 형식으로 재생성, 파일의 서식 변경, 데이터베이스 생성과 데이터를 이용한 수학 계산에 사용합니다. awk라는 이름은 프로그램 제작자들의 이름인 Aho, Weinberger, Kernighan의 앞글자들을 따서 만든 겁니다. 그 외에 awk의 최신 버전에 해당하는 nawk라는 것이 있고 GNU 버전인 gawk라는 것도 있습니다. 리눅스의 경우 awk 명령어가 심볼릭 링크를 통해 gawk를 가리키고 있는 경우가 많습니다. 참고로 우분투의 경우 awk가 심볼릭 링크를 통해 mawk(mike's awk)라는 프로그램으로 링크되어 있는데 사실상 둘이 다를 게 거의 없기 때문에 신경쓰지 않아도 됩니다.

  awk는 표준 입력(=stdin, 키보드로부터 받은 입력), 파일, 다른 프로세스의 출력으로부터 데이터를 받습니다. 데이터를 받으면 입력한 패턴과 일치하는 줄을 찾습니다.


awk 사용
awk [ -F<char> ] {pgm} | { -f <pgm_file> } [ <vars> ] [ - | <data_file> ]
  • char: 필드 구분 문자
  • pgm: 실행할 명령어
  • vars: 변수
  • data file: 입력 데이터 파일
  기본적으론 공백이나 탭이 필드 구분 문자로 사용되지만 -F 옵션을 사용하면 다른 문자를 필드 구분 문자로 사용할 수 있습니다. 예를 들어 필드가 콜론(:)으로 나눠져 있을 경우 아래와 같이 사용합니다.
awk -F:

파일 내용을 입력
  아래는 awk를 이용하여 특정 파일에서 지정한 패턴을 찾는 문법과 실제 사용 예로 ps 명령어의 출력 결과를 텍스트 파일로 만든 후 awk를 이용해 "apache"라는 문자열이 있는 줄을 검색하는 것을 보여주고 있습니다.
문법: awk 'pattern' filename

$ ps aux > processes
$ awk '/apache/' processes
apache    2206  0.0  1.0 207376  3972 ?   S   22:20   0:00 /usr/sbin/httpd
apache    2207  0.0  1.0 207376  3972 ?   S   22:20   0:00 /usr/sbin/httpd
...생략...
  아래는 패턴 대신 액션을 사용한 예입니다. 출력 결과가 위와 다른데 그 이유는 "$1"을 사용하여 모든 줄의 첫 번째 필드를 출력하게 했기 때문입니다. 필드 구분 문자를 따로 지정하지 않았기 때문에 공백을 필드 구분 문자로 사용합니다.
문법: awk 'action' filename

$ ps aux > processes
$ awk '{print $1}' processes
root
root
...생략...
  아래는 패턴과 액션을 섞어서 처음 결과에서 첫 번째 필드만 뽑아내는 문법과 예입니다.
문법: awk 'pattern {action}' filename

awk '/apache/{print $1}' processes
apache
apache
apache
2010/12/09 13:55 2010/12/09 13:55