egrep
■ egrep 메타문자 요약
한 개의 문자에 매치시키기 위한 아이템 |
. |
점 |
임의의 한 문자에 매치됨 |
ex) egrep?'2005.01.05'?file |
2005, 임의의 한 글자, 01, 임의의 한 글자, 05에 매치
<2005/01/05, 2005-01-05, 2005.01.05> |
[...] |
문자클래스 |
열거된 임의의 문자에 대응됨 |
ex) egrep?'gr[ea]y'?file |
g, r, e(or)a, y에 매치 <grey, gray> |
[^...] |
부정형 문자클래스 |
열거되지 않은 임의의 문자에 매치 |
ex) egrep?'pu[^t]'?file |
p, u 뒤에 t가 오지 않는 행만 매치 |
\char |
이스케이프 처리된 문자 |
char이 메타문제이거나 이스케이프 처리된 내용에 별도의 특별한 의미가 없다면 char문자에 매치 또는 새로운 메타문자를 정의함 |
ex) egrep?'\$[0-9]+'?file |
행의 마지막을 의미하는 $의 의미를 그냥 돈의 단위인 $로 매치시킴 <$40> |
|
뒤에 붙어서 '숫자를 세는' 역할을 하는 아이템 |
? |
물음표 |
한번 나올 수 있지만 없어도 됨 |
ex) egrep?'html?'?file |
h, t, m 뒤에 l이 나올 수도 있고 나오지 않아도 되는 행에 매치 <html, htm> |
* |
별표 |
반복회수에 제한이 없으며 아예 없어도 됨 |
ex)
egrep?-i?'<hr(?+size?*=?*[0-9]+)??*>?file |
?이 한번이 나와도 되고 아니면 나오지 않아도 됨 즉 <hr size = 14 > (or) <hr size=14> 등의 스크립트에 매치 |
+ |
플러스 |
적어도 하나 있어야 되며 숫자에 제한이 없음 |
ex)
egrep?-i?'<hr(?+size?*=?*[0-9]+)??*>?file |
?이 한번 이상 나오는 경우에 적용됨 즉 htm 스크립트에서는 절대로 hrsize라고 붙여쓰지 않음을 말함 또, [0-9]는 숫자 하나에 대응하지만 숫자가 하나이상 나올 수 있음을 의미 |
min,max |
주어진 범위 |
최소값과 최대값 사이에서 회수가 제한됨 |
|
위치에 매치되는 아이템 |
^ |
캐럿 |
행 시작되는 위치에 매치됨 |
ex) egrep?'^cat'?file |
c, a, t으로 시작하는 행만 매치 |
$ |
달러 |
행 끝나는 위치에 매치됨 |
ex) egrep?'cat$'?file |
c, a, t으로 끝나는 행만 매치 |
\< |
단어 앞경계 |
단어의 시작 위치에 매치됨 |
ex) egrep?'\<cat'?file |
c, a, t으로 시작하는 단어만 매치 |
\> |
단어 뒤경계 |
단어의 끝 위치에 매치됨 |
ex) egrep?'cat\>'?file |
c, a, t으로 끝나는 단어만 매치 |
|
기타 |
| |
선택(or) |
"|"로 분리되는 표현식 중 하나에 매치됨 |
ex) egrep?-i?'^(from|to)'?file |
f, r, o, m이나 t, o로 시작하는 행에 매치 |
(...) |
괄호 |
① 선택의 범위를 제한하거나 ② 수량자가 적용되는 그룹을 지정하거나 ③ 백레퍼런스를 쓸 때 위치를 지정하기 위한 메타 문자 |
ex) egrep?-i?'^(from|to)'?file |
^의 선택범위를 제한하기 위해서 사용됨 |
\1, \2 |
백레퍼런스 |
앞에서 첫 번째, 두 번째,... 등의 괄호 안에서 매치된 텍스트에 매치됨 |
ex) egrep?-i?'\<([a-z]+)?+\1\>'?file |
\1은 ([a-z]+)에 매치 <옆의 예는 중복단어 체크 매치시키는 표현식> |
■ 앞의 표를 이해하는데 유의사항
1. 이탤릭체로 적은 것은 egrep의 버전에 따라서 적용을 시킬 수 있는 경우가 있고 없는 경우가 있으니 주의해서 사용하기 바란다.
2. ?는 공백의 의미를 사용했다. 이해하는데 무리가 없을 것이다.
■ 생각하는 방식을 바꾸자
ex> egrep 'cat' file
cat이라는 말에 매치되는 행을 찾는 것이 아니라 c 다음에 a 다음에 t가 나오는 행과 매치시키는 것이라고 이해하는 것이 정규표현식을 이해하는 첫걸음이다. 그리고 공백문자를 일반적인 a, b라는 문자와 똑같이 취급을 해야 한다. 공백문자는 컴퓨터는 특별한 무언가로 여기지 않는다.
■ 정규표현식은 언어다. 우리가 어떤 언어를 배우던지 자꾸 써보고 연습해 보는 것이 중요하듯이 정규표현식도 마찬가지다. 그래서 다양한 방법으로 표현된 정규표현식을 익히는 것이 중요하다.
■ grep에서 매칭을 진행하기 전에 일반적으로 \n인 줄바꿈 문자를 잘라내고 진행한다. 그래서 vi 편집기에서 찾을 수 있는 \n은 grep 에서는 찾을 수 없다.
■ 어떤 문자가 메타문자인지 아닌지는 정규표현식에서 문자가 있는 위치가 결정한다. 예를 들어서 *는 메타문자이지만 \* 인 경우는 escape된 경우이므로 메타문자가 아니다. 또 ^의 경우는 행의 제일 앞을 뜻하나 [^...] 의 경우에서는 ...에 매치되는 문자를 제외한 모든 문자에 매치시킨다. 한 가지의 예를 더 들어보자. -의 경우는 [a-z] 안에 있을 경우는 범위를 나타내지만 []밖에 있을 때는 그냥 -문자에 대치된다.
■ 지나치게 자세하게 찾으려는 표현식은 실용성을 떨어뜨린다.
우리가 보통 날짜를 나타날 때 2005/01/05 또는 2005.01.05 또는 2005-01-05으로 나타내는데 그래서 우리는 위의 세 가지의 경우를 매치시키기 위해서 다음과 같은 정규표현식을 사용할 것이다. ex> egrep '2005[./-]01[./-]05' file 그렇게 한다면 우리는 정확히 위의 세 가지 표현에 정확히 매치시킬 수 있지만 다소 타이핑의 수가 많아지게 된다. 그래서 우리는 다음과 같은 차선책을 택할 수 있다. ex> egrep '2005.01.05' file 경제적으로 찾을 수 있다. 하지만 이 표현식의 경우는 다음과 같은 위험이 따른다. 만약 2005901?05345 라는 일정한 배열의 숫자가 있다면 이 행도 찾는 결과를 가져온다. 따라서 우리는 경우에 따라서 정확성과 경제성 사이에서 적절하게 선택을 할 필요가 있다.
■ 위의 표현식이 모든 프로그램이나 편집기에 적용된다는 생각은 하지 말도록 부탁한다. 다른 프로그램에서는 좀 더 복잡한 형태로 정의된다. 다른 프로그램에서 정규표현식을 사용할 경우는 반드시 실험적으로 사용하고 난 뒤에 사용하거나 reference를 참고해서 사용해야 한다.
■ 문자클래스[]는 정규표현식 언어와 전혀 상관없이 별도의 메타문자를 사용
■ 이스케이프 처리되는 경우는 다음의 세 가지의 경우로 나눌 수 있다.
1. \ 뒤에 메타문자를 사용하면 그 문자 자체가 가지는 형태로 매치된다. 예를 들어서 \* 라고 쓰면 스크립트 상에 있는 * 에 매치된다.
2. \ 뒤에 메타문자가 아닌 문자를 쓰면 언어(language)에 따라서 다른 의미를 가지는 메타문자가 된다. 예를 들어 \< 이면 단어의 시작을 의미하는 메타문자가 된다.
3. \ 뒤에 일반적인 문자가 오면 \ 의 의미는 없는 것으로 치부해도 된다. 하지만 \1 , 의 경우는 백레퍼런스로 사용된다.
awk
■ awk란
? awk는 두 가지 측면을 가지고 있다. 하나는 단순한 Text 편집기로서의 측면과 좀 더 복잡한 연산을 수행하는 프로그램의 측면으로 나눌 수 있다. awk 하나만 잘 해도 웬만한 정도의 C program을 대신할 수 있을 정도의 힘을 가질 수 있다. (C program과 문법이 비슷하다.) 본론으로 들어가기 앞서는 왜 awk가 의미하는 것이 무언인지 알아야 하지 않을까. awk 는 Aho, Weinberger, and Kernighan 이 세 분의 initial을 따서 이름한 것이다. 그럼 본론으로 들어가서......
■ awk 둘러보기
? 다음은 예제 파일들이다.
(파일명 : exe4.txt)
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz Josef 100 Korona
silver 10 1981 USA ingot
gold 1 1984 Switzerland ingot
gold 1 1979 RSA Krugerrand
gold 0.5 1981 RSA Krugerrand
gold 0.1 1986 PRC Panda
silver 1 1986 USA Liberty dollar
gold 0.25 1986 USA Liberty 5-dollar piece
silver 0.5 1986 USA Liberty 50-cent piece
silver 1 1987 USA Constitution dollar
gold 0.25 1987 USA Constitution 5-dollar piece |
(파일명 : exe5.txt)
12;466;125;567;0.435
35;366;454;422;0.4565
35;36;45;42;0.45
34;45;235;236;0.454
567;55;233;446;0.56
34;0.53 |
ex1) awk '/gold/' exe4.txt
gold라는 문자를 가진 행을 출력한다.
ex2) awk '/gold/ {print $5,$6,$7,$8}' exe4.txt
gold라는 문자를 가진 행중에서 5, 6, 7, 8 열 만 출력해 준다.
ex3) awk '{if ($3 < 1980) print $3, " ",$5,$6,$7,$8}' exe4.txt
3번째 열이 1980보다 작은 행중에서 3, 5, 6, 7, 8열만 출력해 준다. (간격을 ?? ?? 벌려서 만큼 출력한다.
ex4) awk '/gold/ {ounce+=$2 END print "sum = "ounce}' exe4.txt
gold라는 문자를 가진 행에서 두 번째 열을 더한 값을 ounce에 저장해서 그 값을 sum = 과 함께 화면에 출력을 해 준다.
■ awk 문법
1. TEXT 편집문으로서의 awk문법
문법 : awk [-F<ch>] (pgm] | -f <pgm_file> [<vars>] [- | <data_file>] |
ch : field separator character (필드 구분 문자) |
pgm : awk command-line program (awk 명령문) |
pdm_file : file containing an awk program (awk program이 있는 파일) |
vars : awk variable initialization (awk 변수 초기화) |
data file : input data file (입력하는 파일) |
2. PROGRAM으로서의 awk 문법
#!/bin/awk |
BEGIN |
<search pattern 1> |
<search pattern 2> |
<awk program syntax> |
END |
■ 검색 패턴 (search pattern)
/The/ |
The를 포함하는 행을 찾아준다. |
/^The/ |
첫 글자가 T로 시작하는 것 중에서 다음 문자가 he가 나오는 행을 찾아준다 |
/The$/ |
T h e로 끝나는 문자가 있는 행을 찾아준다. |
/$/ |
$가 있는 모든 행을 찾아준다 |
/[Tt]he/ |
The 나 the가 있는 행을 모두 찾아준다. |
/[a-z]/ |
a부터 z까지 한 문자가 있는 행을 찾아준다 |
/[a-zA-Z0-9]/ |
다 알죠?? |
/wh./ |
wh와 그 다음의 임의의 한 문자와 대응한다.(why, who wh2 등등) |
/^[+-]?[0-9]+$/ |
+or -를 가지고 있거나 없는 거나(++ -- +-는 매치되지 않음) 그 다음은 숫자가 하나이상 나오는 것인데 단어가 숫자로 끝나는 것에 매치한다. |
/(^Korea)|(^China) |
Korea 나 China에 매치된다. |
■ 내부변수
FILENAME |
현재 입력한 파일명 |
FS |
필드 구분자 (초기값 0) |
NF |
필드의 개수 |
NR |
현재 파일의 행 번호 |
OFS |
output의 field separator |
$0 |
전체 입력 파일의 필드 |
■ 유용한 명령들
ex1) awk -F ";" '{print NR,$1,$2,$3,$4,$5}' exe5.txt
필드 구분 연산자를 공백에서 ;로 바꾸어 줌으로써 awk를 연산하고 있다.
ex2) awk '{if (NR >2) print $0}' exe5.txt
행 수가 3이상인 행만 출력한다.
ex3) awk '{if (NF >2) print $0}' exe5.txt
열 수가 3이상인 행만 출력한다.
ex4) awk '{if (length($0) >10) print FILENAME,$0}' exe5.txt
행의 단어 수가 11이상인 행만 출력한다.
ex5) awk '{if (length($0) >10) printf("line %2d is %5.3f %6.2f %5.3f, %5.3f %5.4f ", NR, $1,$2,$3,$4,$5)}' exe5.txt
printf 문의 형태가 C program과 일치하는 것을 알 수 있다. 우리는 쉽게 파일에 나오는 수들의 자리 수들을 쉽게 조절할 수 있다.
ex6) awk '{print system(ls),FILENAME,$0}' exe5.txt
system()은 UNIX 명령문을 처리하게 해 준다. 그리고 그 처리한 결과가 정상적으로 실행이 되었다면 그 결과로써 0을 리턴해 준다. 만약 실패하였다면 다른 값을 줄 것이다.
ex7) awk '{print toupper($1), $2, $3}' exe4.txt
toupper()은 괄호 안에 있는 문자를 대문자로 변환을 시켜서 출력을 시켜준다.
ex8) awk 'print {tolower($1), $2, $3}' exe4.txt
toupper()은 괄호 안에 있는 문자를 소문자로 변환을 시켜서 출력을 시켜준다.
ex9) awk -F ";" '{print sqrt($1), $2, $3}' exe5.txt
$1을 제곱근 해 준 값이 출력된다. sqrt뿐만 아니라 다음의 함수들도 존재한다. 효과적으로 이용하시길... atan2(y,x) : 아크 탄젠트 y/x를 출력, cos(x), sin(x), exp(x), log(x), int(x)
ex10) awk '/silver/ {++x END print x}' exe4.txt
silver와 일치하는 패턴의 줄 수를 구해 주는 것이다. 이것과 똑같은 결과를 얻기 위한 명령으로는 grep ??silver?? exe4.txt | wc -l 이 있다.
ex11) awk '$1~/silver/ {print $0}' exe4.txt
$1에서 silver에 매치되는 행들만 출력해준다. 이 명령은 좀 더 유연한 명령을 실행시켜 명령의 완성도를 높인다고 볼 수 있다.
ex12) awk '{gsub("from","to");print}' exe2.txt
from을 to로 모두 치환해서 화면에 출력해 준다.
ex13) awk -F";" '{if(($1>30) &&($2>100)) print $0}' exe5.txt
첫 번째 열이 30보다 크고 그리고 두 번째 열이 100보다 큰 것을 출력해준다.
■ awk 프로그램 예제
1. 합계 구하기
#!/bin/awk
#파일명 : sum.awk
#첫 번째와 두 번째 열을 읽어 들여서 각각의 산술평균을 구하는 awk 프로그램
#사용법 : awk -f sum.awk filename
BEGIN
x_sum = 0;
y_sum = 0;
print "Xcen_image";
print "Ycen_image";
x_sum +=$1;
y_sum +=$2;
n++
x_average = x_sum/n ;
y_average = y_sum/n ;
END print "x_sum :" x_sum ;
printf("%d ", x_average);
print "y_sum :" y_sum;
print "y_average :" y_average;
|
2. 중복되는 행 출력하지 않게 하기
#!/bin/awk
#파일명 : uniq.awk
#첫 번째 열이 같은 행은 출력하지 않고 첫 번째 열이 다른 것이 나오는 행을 출력한다.
#사용법 : awk -f uniq.awk filename
BEGIN FS = " "
if (var != $1 && NR != 1)
print line
var = $1
line = $0
END print line |
3. 첫 번째 열을 인자로 사용하는 배열을 사용하여 같은 인자를 가지는 배열일 경우에는 그 합을 구해주기
#!/bin/awk
#파일명 : array.awk
#사용법 : awk -f array.awk filename
BEGIN FS=";"
OFS=":"
total[$1] += $2;
if( lastcategory != $1)
printf("lastcategory != $1 ");
print $1;
lastcategory = $1
printf( " ");
print $1,$2;
END printf(" "); print "TOTALS";
for(category in total)
printf(" ");
print category, total[category];
|
이의 사항이 있거나 질문이 있으시면 이곳으로 이메일을 보내주세요 Webmaster
Copyright ⓒ 2005 All Rights Reserved by Hahn Yi