김선영 sunyzerogmail dotcom 버 전 20141222 가메 출판사 httpwwwkamecokr 인사이트 httpbloginsightbookcokr 저자블로그 httpsunyzerotistorycom ID: 293738
Download Presentation The PPT/PDF document "awk / shell programming" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
awk / shell programming
김선영sunyzero@gmail(dot)com버 전: 2014-12-22
가메
출판사
http://www.kame.co.kr
인사이트
http://blog.insightbook.co.kr
저자블로그
http://sunyzero.tistory.comSlide2
awksyntax, practiceSlide3
What is awk?설계자인 Aho. Weinbrger, Kernighan
의 머릿글자에서 유래/ɔːk/ 라고 읽는다.공식적으로 "패턴 검색과 처리언어"라고 정의독자적인 처리 문법과 언어 구성을 갖추고 있음expr, grep, sed의 모든 기능을 포함하고 있음grep, sed로 처리가 불가능하다면 awk를 사용gawk (GNU awk) - 확장된 기능 제공이 강의는 gawk를 기준으로 작성되었으나 대부분의 표현식은 POSIX awk에서도 잘 작동합니다.Slide4
awk commandawk의 실행 방법
awk script는 single quotes로 묶는다. Why?GNU awk(gawk)에서 POSIX로 작동하려면 --posix 옵션을 준다.awk [-F
필드구분자
] '
스크립트코드
' <
처리할파일
>...
awk [-F
필드구분자
] -f <awk스크립트파일> <처리할파일>...
실행 명령어만 알아도 절반은
먹고 들어가는 법이다
!Slide5
awk CLIdata file : account.txt
# UNIX ACCOUNT : No.00704sunyzero:Sunyoung Kim:1600:AA-1342R:010-2007-8080:19991222ppan:Peter Pan:1200:CC-0100R:010-3593-1277:19921202clyde47:John Smith:650:CC-1106R:010-6532-1004:20000123banaba:John Kennis:1100:CA-0971R:010-4321-1234:20000123
jamtaeng:Jambo
Park:880:AD-1000R:010-6420-3578:19970802
$
awk -F : '{print $1, $4;}' account.txt
# UNIX ACCOUNT
sunyzero AA-1342R
ppan CC-0100R
clyde47 CC-1106R
banaba CA-0971Rjamtaeng
AD-1000R
-F : # field separator
$1, $4 # fields
print
명령은 자동 개행
!Slide6
awk script filedata file : account.txt
$ cat pr_1a4.awk{ print $1, $4 }
$
awk -F : -f pr_1a4.awk account.txt
# UNIX ACCOUNT
sunyzero AA-1342R
ppan CC-0100R
clyde47 CC-1106R
banaba CA-0971R
jamtaeng
AD-1000R-f file # script filenamecomma의 역할은? print $1 $4로 해보자Slide7
awk script block조건/
패턴이 true일 때 { command; ... } 실행[ condition or
pattern
] {
command;
...
}
$
awk
-F : 'NR>1 { printf "%s(%s)\n",$1,$2 }' account.txtsunyzero(Sunyoung Kim)ppan(Peter Pan)clyde47(John Smith)banaba(John Kennis)jamtaeng(Jambo Park)NR>1 # Line numberprintf # formatingSlide8
printfC-style formatting
%[flag][x][.y]cflag플래그 지정
: -, 0, '
등을 지정할 수 있음
.
x
최소 필드 너비
(min. field width)
를 지정
.y
정밀도 지정
c
변환형 지정
: s,d,f,s,c ...
등등을 지정할 수 있음
.
flag
설명
-
왼쪽으로 정렬
0
숫자 출력시 빈공백 부분을
0
으로 채움
'
숫자 출력시 천
(thousand)
단위로 점을 찍을때 사용
홀 따옴표에 주의Slide9
printf : single quotes홀 따옴표 사용 주의
결론 : escape가 필요하다.하지만 %\'10d으로 하면 single quotes로 인해escape전과 다를 바가 없다.Slide10
printf : single quotes (con't)escape
를 위한 블록 분리1000단위 출력이 실패하는 경우LC_LOCALE이 설정된 경우(or LANG의 영향)홀 따옴표에 주의(쌍 따옴표 아님
)Slide11
printf: conversion (C-style)
변환형설명d, i10진수 정수형
u
10
진수 양의 정수형
o
8
진수 양의 정수형
x, X
16
진수 양의 정수형f, F
실수형
e, E
실수형
(
scientific notation
으로 지정된
)
e.g. 1.23456e+05
c
숫자인 경우
ASCII
코드로 변환하여 문자
1
개 출력
문자열인 경우 맨앞 한개의 문자만 출력
s
문자열 출력Slide12
printf: practice
숫자 출력 예제Slide13
printf: practice (con't)
문자열 출력 예제Slide14
awk fieldfield 선택
awk variablestring, integer, real number 모두 지원$ awk -F: 'NR>1 {var
=$2;$2=$3;$3=var; print}'
account.txt
sunyzero 1600 Sunyoung Kim AA-1342R 010-2007-8080 19991222
ppan 1200 Peter Pan CC-0100R 010-3593-1277 19921202
clyde47 650 John Smith CC-1106R 010-6532-1004 20000123
banaba 1100 John Kennis CA-0971R 010-4321-1234 20000123
jamtaeng 880 Jambo Park AD-1000R 010-6420-3578
19970802
2th, 3th 필드의 스왑Slide15
Pratice조건 적용하여 출력해보자.
$ awk 'NR>1 {printf "%d:%s\n",NR-1,$1}' account.txt1:sunyzero:Sunyoung2:ppan:Peter
3:clyde47:John
4:banaba:John
5:jamtaeng:Jambo
$
awk -F: 'NR>1 {printf "%d:%s\n",NR-1,$1}' account.txt
1:sunyzero
2:ppan
3:clyde47
4:banaba5:jamtaengSlide16
awk pattern패턴 형식
/regular expression/relational expressionpattern && pattern
pattern
|| pattern
pattern
? pattern : pattern
(
pattern)
!
pattern
pattern1, pattern2pattern { .... }
range
패턴은 데이터 파일을 처리하는데 유용하다
.Slide17
pattern: REGEX/REGEX/ 를 이용하여 조건 사용
$ awk '/C[A-Z]-[0-9A-Z]+/ {print}' account.txtppan:Peter Pan:1200:CC-0100R:010-3593-1277:19921202clyde47:John Smith:650:CC-1106R:010-6532-1004:20000123
banaba:John Kennis:1100:CA-0971R:010-4321-1234:20000123
$
awk -F: '$
4 ~ /C[A-Z]-[0-9A-Z]+/ {print}' account.txt
ppan:Peter Pan:1200:CC-0100R:010-3593-1277:19921202
clyde47:John Smith:650:CC-1106R:010-6532-1004:20000123
banaba:John Kennis:1100:CA-0971R:010-4321-1234:20000123Slide18
operator
OperatorDescriptionExample
==, !=
equality operator, not equal to
$1=="Fred", $4!=NF
<
less than
$1<$3
<==
less than or equal to
$1<=$1+NR
>
greater than
$10>100
?:
Condition operator (equal to C)
~
contain regular expressions (match)
$4~/LOC/ , $9~/[A-Z]/
!-
Dose not contain regular expression
$9!~/..[a-z]/Slide19
operator (con't)blank line을 제외하고 첫번째 필드가
100보다 큰 경우범위 연산을 사용하는 경우$ awk '($0 !~ /^$/) && ($1 > 100) {print $0}' datafile.txt
$
awk '(
NR == 3),(NR ==
10)'
/etc/passwdSlide20
operator (con't)다양한 패턴 조합이 가능하다.
데이터 파일 내부에 start, end를 명시하는 comment line이 있다면 패턴으로 걸러내서 읽을 수 있다./^[^#]+/ { print }/^[^#]+/ || $0 !~ /^$/
{ print }
/^#start data/,/^#end data/
{ print }
(NR == 5),/^#end of file/
{ print }Slide21
BEGIN, ENDBEGIN연산이 일어나기 에 수행
initialization, pre-processing 작업END연산이 끝난 뒤에 수행주로 출력을 수행한다.BEGIN { action }pattern { action }
...
END { action }Slide22
BEGIN, END (con't)BEGIN 사용 방식
END 사용 방식$ awk 'BEGIN {FS=":"} (NR == 3),(NR == 10)' /etc/passwd
$
awk 'END { print NR }' /etc/passwd
34
$
wc -l /etc/passwd
34 /
etc/passwdSlide23
BEGIN, END (con't)BEGIN, END를 이용한 계산
$ cat pi.awkBEGIN { print "Pi (numerical integration method)" }{ n_steps = $1; sz_step = 1.0/n_steps; sum=0.0; }END {
for (i=0; i<n_steps; i++) {
x = (i+0.5) * sz_step;
sum += 4.0/(1.0 + x*x);
}
printf("n_steps = %d, sz_step = %.8f\n", n_steps, sz_step);
printf("pi = %.8f, 4*atan(1) = %.8f\n", sz_step*sum, atan2(1,1)*4);
}
$
time echo 2000000 | awk -f pi.awkPi (numerical integration method)
n_steps = 2000000, sz_step = 0.00000050
pi = 3.14159265, 4*atan(1) = 3.14159265
real 0m0.546s
user 0m0.544s
sys
0m0.001s
atan2() - arc-tangent in radians angleSlide24
built-in var.
변수명의미
ENVIRON
환경 변수들을 모아둔 관계형 배열
ARGC
커맨드 라인 아규먼트의 갯수
ARGV
커맨드 라인 아규먼트의 어레이
FILENAME
문자열
=
현재 입력 파일명
FNR
현재
file
의 현재 레코드 번호
(
각 입력 파일에서
1
부터 시작한다
.)
FS
입력 필드
seperator
문자
(
기본값
=
공백
)
NF
현재 레코드의 필드 번호
NR
현재의 레코드 번호
(
모든 입력 파일을 통틀어
)
FIELDWIDTHS
FS
대신에 사용할 고정 필드 크기
(
구분자가 없는 데이터 처리시 사용한다
.)
OFMT
숫자를 위한 출력 포멧
(
기본값
= %.6g)
OFS
출력 필드
seperator (
기본값
=
스페이스
)
ORS
출력 레코드
seperator (
기본값
=
개행문자
)
RS
입력 레코드
seperator (
기본값
=
개행문자
)
SUBSEP
배열에 쓰는 첨자 구획 문자
RSTART
매칭 연산
(match function)
을
만족하는 문자열의 맨 앞부분
RLENGTH
매칭 연산
(match function)
을
만족하는 문자열의 길이
IGNORECASE
대소문자 무시
*
*
IGNORECASE
관련 함수
: gensub(),
gsub(), index(), match(), split
(), sub()Slide25
flow control
Flow control statementDesc.
if (conditional)
{
statement_list1}
[else
{
statement_list2}]
C-style if
while (conditional)
{statement_list}
C-style
while
for (init;condition;ctrl
)
{
statement_list}
C-style for loop
break
루프를 종료시키고 다음
statement
로 넘어가게 한다
.
continue
현재 위치에서 루프의 다음
iteration
으로 넘어가게 한다
.
next
현재
input line
에 대해서 남아있는
pattern
을
skip
exit
남아있는
input
을 모두
skip
한다
.
만일
END pattern
이 있다면
처리한 후
awk
를 종료시킨다
.Slide26
print , var control
print control statementprint [expr_list] [>file]
expr_list
에 있는
expression
을
stdout
이나 특정 파일로
리다이렉트 한다
.
file은 file descriptor를 사용한다.
printf format [,expr_list] [>file]
C
언어의
printf
문과
동일
포맷된
형식의
expression
을 보여준다
.
출력은
위와 같다
.
sprintf (format [,expression])
C
언어의
sprintf
처럼 버퍼에 리턴하기만 하고
,
출력하지
않는다. 변수에 저장할 때 사용한다.
assignment statement
variable=awk_expr
awk expr
에서 나온
expression
을
variable
에 할당한다
.
userdefined fd
는
3-19
까지 사용 가능하다
.
printf
의
default precision
은
6
자리이다
.Slide27
Practice합산 계산,
새로운 필드 할당$ cat score.txt#name:math1:math2:datastructure:algorithmJack,78,45,68,49Mick,77,32,86,67
Fred,95,55,85,62
Kim,88,42,85,60
$
awk
-F,
'NR>1 { $6
=$2+$3+$4+$5;
print $0 }'
score.txtJack 78 45 68 49 240Mick 77 32 86 67 262Fred 95 55 85 62 297Kim 88 42 85 60 275
$
awk
-F,
'$0 !~ /^#.*/ { $6=$2+$3+$4+$5; print $0 }'
score.txt
...생략...
6th field
는 새로 할당된 필드다
.Slide28
Practice (con't)2번째 과목의 평균 계산
$ cat avg.awk$0 !~ /^#.*/ { sum += $3 }END { printf "math2 avg = %.2f\n", sum/(NR-1) }$ awk -F, -f avg.awk score.txtmath2 avg = 43.50Slide29
PracticeSystem daemon의
Minor pagefault, RSS 계산$ cat chk_sysdaemon.sh#!/bin/bash
ps -eo user,uid,pid,ppid,sz,rss,vsz,min_flt,maj_flt,cmd |
awk '
BEGIN { n_ps=0; n_tot_minflt=0; n_tot_rss=0; }
($1 == "root") && ($4 == 1)
{ n_ps++; n_tot_minflt+=$8; n_tot_rss+=$6; }
END {
printf "-------- Daemon process monitor --------\n";
printf "Processes\tMin.PageFault\tTotalRSS\n";
printf "%9d \t %12d \t %7d\n", n_ps, n_tot_minflt, n_tot_rss;}'Slide30
functionlength(x)는
x의 길이를 리턴한다.$ awk -F: '(length($2)<11 && NR>1) {printf "%d:%s,%s\n",NR-1,$1,$2}' \
account.txt
2:ppan,Peter Pan
3:clyde47,John Smith
5:jamtaeng,Jambo ParkSlide31
function: string
function namedescription gsub(r,s[,t])
정규표현식
r
과 매치되는 문자열
t
를
s
로 대치한다
.
(t를 지정하지 않으면 $0 ; 문자열 자체가 변경되니 조심할 것!)
* return value :
대치에 성공한 패턴 개수
(
양수
)
index(str1,str2)
Returns the starting position of str2 in str1.
If str2 is not present in str1, then 0 is returned
length(str)
Returns the length of string str
match(s,r)
문자열
s
에서 정규표현식
r
과 매치되는 부분의 위치를 넘겨준다
split(str,array[,sep])
구분자
sep
를 기준으로
(default
는
space
)
문자열
str
을
배열로
변환
sprintf(fmt,awk_exp
)
Returns the values of awk_exp formatted as defined by
fmt
sub(r,s[,t])
정규표현식
r
과 매치되는 문자열
t
를
s
로 대치한다
.
gsub
와 다른점은
t
에서
r
과 매치되는 부분이
여러 개라
할지라도
처음
한 개만 대치한다는 것이다
.
* return value:
대치에 성공한 패턴 개수
(0
or 1)
* gawk
는
gsub, sub
의
general version
인
gensub
를 지원한다
.
* gawk
는
strtonum()
으로
base
진수로 표기된 문자열을 숫자로 변환할 수 있다
.
*
gsub (global sub)Slide32
function: string
function namedescription substr(str,start,length)
Returns a substring of the string str starting at position start for length characters
ex) substr("believe", 3, 5) == "lieve"
tolower(str)
문자열
str
을 모두 소문자로 바꾼다
toupper(str)
문자열
str
을 모두 대문자로 바꾼다Slide33
function: math
function description (angle은 모두 radian으로 쓴다)
int(x)
x
의 소수점 이하 값을 버린다
.
rand()
0
에서
1
사이의
random variable
을 취한다
.
srand(x)
rand
을 위해
x
를 새로운
seed
로
setting
(
특정값이나
새로운
랜덤 변수
발생시
사용
)
cos(x)
x
의
cosine값을 리턴sin(x)
x
의
sine
값을 리턴
atan2(x,y)
y/x
의
arc tangent
값을 리턴
exp(x)
e^x
의 값을 리턴
(
무리수
e
의
x
승 값
)
log(x)
log_e x
의 값을 리턴
(
자연로그
x
값을 리턴
)
sqrt(x)
음수가 아닌
x
의 루트값
(
the radical sign, value = x)Slide34
function: date, time
function description
systime()
UNIX epoch
timestamp
를 리턴한다
.
strftime([fmt [,
timestamp
]])
C-style strftime
$
awk 'BEGIN { print systime()
}'
1400908965
$
awk 'BEGIN { print strftime("%Y%m%d-%H%M%S %z") }'
20140524-143007 +
0900Slide35
Practice : function : substrsubstr - substring
$ cat contdata.txtB6011KR70053800010000003886390002340000002335000000000030310B6012KR70357600080000000082690003844000003843000000000000140
B6011KR70059300030000001237900014410000014400000000000007510
B6011KR70059300030000001238240014410000014400000000000007270
B6012KR70357600080000000126490003837000003836000000000000280
B6011KR7005380001
000000388663
0002340000002335000000000030310
$
awk 'substr($
0,6,12) == "KR7005380001" { print substr($0,18,12) }' \contdata.txt000000388639000000388663Slide36
Practice : function : matchPOSIX awk에서는
{n,m} 표현을 지원하지 않는다.--re-interval 옵션 : REGEX interval expression을 지원--re-interval 대신에 --posix 으로 실행해보자.gawk manual>>extensions in gawk Not in POSIX awk 참고
$
gawk --re-interval \
'match($0,/KR[0-9]{10}/) { print substr($0,RSTART+3,RLENGTH-6)
}' \
contdata.txt
005380
035760
005930
005930035760005380Slide37
Practice : function : gsub, sub, gensubsubstitution function
$ cat contdata.txtB6011KR70053800010000003886390002340000002335000000000030310B6012KR70357600080000000082690003844000003843000000000000140
B6011KR70059300030000001237900014410000014400000000000007510
B6011KR70059300030000001238240014410000014400000000000007270
B6012KR70357600080000000126490003837000003836000000000000280
B6011KR7005380001
000000388663
0002340000002335000000000030310
$
awk --re-interval '{ sub(/KR7[0-9]{9}/, "###123456789"); print }'
\contdata.txtB6011###1234567890000003886390002340000002335000000000030310B6012###1234567890000000082690003844000003843000000000000140B6011###1234567890000001237900014410000014400000000000007510B6011###1234567890000001238240014410000014400000000000007270
B6012###1234567890000000126490003837000003836000000000000280
B6011###
1234567890000003886630002340000002335000000000030310Slide38
Practice : function : gensubgensub(regex, replace, how [,target var.])
gawk를 사용한다면 gensub는 매우 유용하다.$ awk '{ a=gensub(/([0-9]+)/, "(\\1)", "g")
; print a}' /
etc/passwd
...
생략
...
sunyzero:x:(500):(500):SY Kim:/home/sunyzero:/bin/bash
$
awk
'{ a=gensub(/([0-9]+)/, "(\\1)", "1"); print a}' /etc/passwd...생략...
sunyzero:x:(500
):500:SY
Kim:/home/sunyzero:/
bin/bash
$
awk
'{ a=
gensub(/([0-9]+)/, "(\\1)",
"2")
;
print a}' /etc/passwd
...
생략
...
sunyzero:x:500:(500):
SY Kim:/home/sunyzero:/bin/bash
* how : g (global) , index (replace the n-th field)Slide39
Practice : function : gensub (con't)substitution function - backreference
를 지원하는 gensub$ cat contdata.txtB6011KR70053800010000003886390002340000002335000000000030310B6012KR70357600080000000082690003844000003843000000000000140
B6011KR70059300030000001237900014410000014400000000000007510
B6011KR70059300030000001238240014410000014400000000000007270
B6012KR70357600080000000126490003837000003836000000000000280
B6011KR7005380001
000000388663
0002340000002335000000000030310
$
awk
--re-interval '{ a=gensub(/KR7([0-9]{9})/, "###\\1", "g"); print a}' \contdata.txtB6011###005380001
0000003886390002340000002335000000000030310
B6012
###035760008
0000000082690003844000003843000000000000140
B6011
###005930003
0000001237900014410000014400000000000007510
B6011
###005930003
0000001238240014410000014400000000000007270
B6012
###035760008
0000000126490003837000003836000000000000280
B6011
###005380001
0000003886630002340000002335000000000030310
* gsub, sub
는
backreference
를 지원하지 못한다
.Slide40
Practice : gen. source codetest_posixopt.awk
BEGIN { cnt = 0 }# get posix options from file.{ elem[cnt++] = $1; }# end; print them; generate C source code.END {
for (i=0; i<=cnt; i++)
{
if (i == 0) {
print "#include <unistd.h>\n#include <stdio.h>\nint main()\n{\n"
} else if (i == cnt) {
print "\treturn 0;\n}"
} else {
printf("#if %s > 0L\n\tprintf(\"[O] %s\\n\");\n", elem[i], elem[i]);
printf("#else\n\tprintf(\"[X] %s\\n\");\n", elem[i], elem[i]); printf("#endif\n"); } }}Slide41
Practice : gen. source code (con't)test_posixopt.txt (
posixoptions manpage 참조)_POSIX_ADVISORY_INFO_POSIX_ASYNCHRONOUS_IO_POSIX_BARRIERS_POSIX_CLOCK_SELECTION
_
POSIX_CPUTIME
...
생략
...Slide42
Practice : gen. source code (con't)Makefile
# MakefileAWK = awkOUT = test_posixoptall: $(OUT).SUFFIXES:
.PRECIOUS: .o
%.c: %.awk
$(AWK) -f $< $*.txt | tee $@
%: %.o
$(CC) $< $(LOADLIBES) $(LDLIBS) -o $@
%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o
$@
clean: rm -f *.o core core.* $(OUT)Slide43
shell variable-v
varname="$shell_var"$ msg="Hello unixer"$
var_r
="
unix
"
$
var_s
="
linux
"$ echo $msg | awk '{gsub($var_r, $var_s);print}'
$ echo
$msg | awk
-v
r1="$var_r"
-v
s1="$var_s"
'{
gsub(r1, s1)
;
print
}'