2장. 정규식과 유틸리티들

 

학습목표

   정규식에 대한 이해 
   grep 

   awk 
   sed

 

1. 정규식에 대한 이해


grep,awk,sed,vi,perl등과 같은 명령어들을 패터처리 언어에서 사용하는 패턴에 대한 특정 규칙을 정규식(Regular Expression)이라고 부른다. 다시 말해서 패턴이란 "규칙적으로 기술된 문자열" 이라고 설명 할 수 있고 이런 규칙들을 표현하는 형식중의 한 방법이 정규식이다.

다음은 샘플 데이터 파일과 egrep 명령을 이용하여 정규식을 하나씩 설명하겠다.

 

<샘플 파일> 
$ cat sampfile 
This is sample data file 
Hello This is Kim. 
I'm so happy 
Test100 
test200 
Are you unhappy ?

 

1) " ^ " : 행의 시작과 부합

$ grep "^H" sampfile 
Hello This is Kim.

 

2) " $ " : 행의 끝과 부합

      $ grep "happy$" sampfile 
      I'm so happy

 

3) " * " : 임의의 0개 이상의 문자와 부합

$ egrep "e*" sampfile 
This is sample data file 
Hello This is Kim. 
I'm so happy 
Test100 
test200 
Are you unhappy ? 
$ egrep "ee*" samplefile 
This is sample data file 
Hello This is Kim. 
Test100 
test200 
Are you unhappy ? 
$ egrep "ppp*" sampfile 
I'm so happy 
Are you unhappy ?

 

4) " ? " : 임의의 0 또는 1개의 문자와 부합

$ egrep "pp?" sampfile 
This is sample data file 
I'm so happy 
Are you unhappy ? 

5) " + " : 임의의 1개 이상 문자와 부합

$ egrep "pp+" sampfile 
I'm so happy 
Are you unhappy ?

 

6) " . " : 임의의 한문자와 부합

$ egrep "y.." sampfile 
Are you unhappy ?

 

7) " \< " : 단어의 시작과 부합

" \> " : 단어의 끝과 부합 
$ egrep "happy" samplfile 
I'm so happy 
Are you unhappy ? 
$ egrep "\<happy\>" sampfile 
I'm so happy 
$ egrep "happy\>" sampfile 
I'm so happy 
Are you unhappy ?



 

8) " [문자들] " : 문자들에 포함되는 하나의 문자와 부합

" ^[문자들] " : 문자들에 포함되는 문자들을 제외한 하나의 문자와 부합 
$ egrep "^[A-Z]" sampfile 
test200 
$ egrep "^[^A-Z]" sampfile 
This is sample data file 
Hello This is Kim. 
I'm so happy 
Test100 
Are you unhappy ? 
$ egrep "[0-9]$" sampfile 
Test100 
test200

 

9) 정규식과 부합하는 문자의 반복횟수

\{숫자\} : 정확히 지정된 숫자만큼 반복 
\{최소값,최대값\}: 최소값부터 최대값까지 횟수 만큼 반복 
ex) a\{1\} a가 정확히 한번 team , happy, goal 
a\{1,\} a가 한번이상 반복 team. aang, aaaang 
a\{2,5\} a가 2번이상 5번 이하 반복 aa, aaa, aaaa, aaaaa 

10) " \( 패턴 \) " : 내부 표현식을 만든다.

패턴을 하나의 문자 처럼 사용한다. 
" \숫자 " : 숫자번째 내부 표현식에 부합된 문자열을 다시 참조한다. 
$ egrep '\([A-Za-z0-9].*\)\(:.*\)\{4\}:/export/home/\1:' /etc/passwd 
결과> /etc/passwd 파일안에서 사용자의 login명과 기본 디렉토리명이 같은 사용자를 검색하여 출력한다.

 

11) " \ " : 정규식의 메타 문자가 아닌 문자 자체로 해석

$ egrep "\.$" sampfile 
Hello This is Kim. 

2. awk

awk 은 설계자인 Aho, Weingrger, Kernighan의 첫글자로 명명되어진 패턴검색과 처리 기능을 가진 인터프리티드 프로그래밍 언어로서 필터링, 치환, 간단한 리포팅 작업을 제어할수 있다.

 

1) "awk" 형식

awk 프로그램은 세부분으로 구성되어 진다.

BEGIN Section : 파일을 읽기전에 실행 
Pattern Statment Section : 파일의 각 레코드 라인을 읽어들일 때 마다 실행 
END Section : 파일을 다 읽어들인 뒤 실행

BEGIN { statements ….} 
/pattern expression / { statements  .... } 
END { statements… }
 

여러개의 statement를 한 라인에 쓸때는 statement ; statement 의 형식으로 기술한다. 

2) awk 명령어 실행 방법

 

"awk" 프로그램을 명령어 상에서 입력하는 경우 
$ awk '{print $0 }' datafile .... 
단일인용문( ' ' ) 안에 프로그램을 기술한다. 데이터 파일을 정의하지 않으면 표준 입력으로부터 데이터를 입력 받는다.

awk 프로그램을 파일로 작성하는 경우는 
$ awk -f awk-program-filename data-filenames

ex) 
$ awk ' BEGIN { print "awk 프로그램 실행 연습입니다" } ' 

$ awk '{ print $1, $2 } ' data1 
100 200 
300 400 
500 600 

$ cat ex01 
# This is sample file 
BEGIN { 
print "Hello, I'm Kim " 
exit } 

$ awk -f ex01 
Hello, I'm Kim



3) 레코드

레코드는 입력된 파일의 한 줄을 말한다. 라인 전체의 내용은 $0 변수명으로 사용되며, 입력된 레코드 번호는 NR 이라는 변수로 표시 된다.

4) 필드

입력된 레코드에서 스페이스 또는 탭으로 구분되는 문자들을 말한다. 각각의 필드는 $1,$2,$3,....$n 으로 필드위치에 따라 변수명으로 표기되며 현재 필드값은 NF 변수로 표시된다.

5) 변수

위치변수 는 필드 또는 레코드를 나타낸다
$0 : 현재 입력된 레코드를 나타내는 변수 
$1 : 현재 입력된 레코드의 첫 번째 필드를 나타내는 변수 
$n : 현재 입력된 레코드의 n번째 필드를 나타내는 변수

재정의 변수는 입력된 레코드의 구성과 크기에 대한 정보를 제공한다
NR : 레코드 수 
NF : 필드 수 
FS : 필드 구분 문자 
RR : 레코드 구분 문자 
OFS : 출력 필드 구분 문자 
ORS : 출력 레코드 구분 문자 
FILENAME : 현재 입력된 파일 이름 
OFMT : 출력 인쇄 형식

사용자 정의 변수는 프로그램의 어느 곳에서도 사용자가 정의하여 사용 할 수 있으며, 숫자 또는 문자열 값을 가진다. 초기화 하지 않으면 자동적으로 null(0) 문자를 가진다.

ex) 
$ cat data1 
100 200 
300 400 
500 600 
$ cat ex02 
BEGIN { OFS="------" } 
{ print $1,$2 } 

$ awk -f ex02 data1 
100------200 
300------400 
500------600 

$ cat ex03 
{ x = $1 + $2 
y = y + x } 
END { print y } 

$ awk -f ex03 data1 
1600 


6) 패턴 과 연산자

 

패턴의 형식은 egrep과 유사한 형식을 가진다. 정규식을 사용하여 패턴을 구성할 수 있으며 패턴은 "/ /" 형식으로 지정한다. 
"/ /,/ /" 형식을 사용하여 패턴으로 범위를 지정할 수 있다.

ex)

$ cat ex04 
$2 ~ /^[0-9]+$/ { print $2 } 
-> 두 번째 필드가 숫자로만 구성되어 있으면 두 번째 필드값을 출력 
$ awk -f ex04 data1 
200 
400 
600 

$ cat ex05 
$0 ~ /[Ee]nd/ { print "end of", FILENAME } 

-> 읽어 들인 레코드의 값이 End 또는 end이면 "end of data1" 과 같은 형식으로 출력 
$ cat ex05_1 
/Begin/,/End/ { total += $1 } 
END { print "Total = " total }

연산자는 관계연산자, 패턴 연산자, 산술연산자, 지정 연산자, 복합지정연산자, 증감연산자 가 있다. 
관계연산자는 숫자 또는 스트링 값을 비교할 때 사용한다.

==            같다 
!=           같지 않다 
>             크다
            작다 
>=            크거나 같다 
<=            작거나 같다

ex)

NF != 5 { print "필드수가 5개가 아님"} 
$1 >= 10000 { print "첫번째 필드값이 10000 보다 크거나 같다" } 
$1 >= "s" { print " 첫 번째 필드가 s 보다 뒷문자(tuvw..)이다"} 
$1 < $2 { print "두번째 필드 값이 첫 번째 필드 값보다 크다"}

 

패턴연산자는 스트링 패턴과의 일치 여부를 비교할 때 주로 사용 된다.

            패턴과 일치 
!~           패턴과 같지 않다.

 

ex) 
$1 !~ /^[0-9]+$/ { print "첫번째 필드가 숫자가 안니다" } 
$2 ~ /korea/ { print "두번째 필드값이 korea 이다"}

 

산술연산자는 수식 계산에 사용된다 
            더하기 
            빼기 
            곱하기 
            나누기 
            나누어서 남은 나머지

 

지정 연산자는 오른쪽 값을 왼쪽 변수에 대입한다 
            지정연산 
ex) a = 10

 

복합 지정 연산자는 산술연산자와 지정연산자를 결합해서 사용한다 
+= , -=, *=, /=, %=

ex) a += 5 : a = a + 5 와 같은 문장이다.

증감 연산자는 값을 1씩 증가하거나 감소 시킬 때 사용한다

++           1 증가 
--           1 감소

ex) 
$ cat ex06 
END { a = 0 
print "a++ = ", a++ 
print "a-- = ", a-- 
exit 
}

$ cat ex07 
BEGIN { a = 0 } 
$1 > 100 { a++ } 
END { print "첫번째 필드의 값이 100보다 큰 경우는 ", a, "번입니다" }
$

$ awk -f ex07 data1 
첫번째 필드의 값이 100보다 큰 경우는 2 번입니다

 

7) 출력문

print 문은 출력하고자하는 문자열은 "출력내용" 의 형식으로, 변수값은 변수명을 사용하여 출력한다. 
" , " (쉼표)는 "print"문 안에서 필드를 구분한다. "" 사이의 문자열은 하나의 필드로 취급된다. 
출력방향을 조정하기위해 " > " 문자와 " >> " 문자를 사용할수 있다. 출력될 파일이름은 인용부호("")안에서 사용한다.

ex) 
$ cat ex08 
{ print $1,$2 > "sample"} 

$ awk -f ex08 data1 
$ cat sample 
100 200 
300 400 
500 600

"printf" 문을 사용하여 출력 양식을 지정할 수 있다. 
사용형식은 printf "format",expression1, expression2,..... 이다. 
format에서 변환사양은 % 기호를 붙여서 표시한다

%d            십진수 
%o            8진수 
%x            16진수 
%s            문자열 
%f            소수 
%e            지수를 사용한 소수 
%g            %f,%e중 짧은 형태의 출력을 사용한다.

ex) 
$ cat ex09 
$1 ~ /^[0-9]+$/ { printf "첫번째 필드 값은 %d 입니다\n",$1 } 

$ awk -f ex09 data1 
첫번째 필드 값은 100 입니다 
첫번째 필드 값은 300 입니다 
첫번째 필드 값은 500 입니다 
$

 

파이프(|)를 사용하여 " print"문의 출력을 UNIX 시스템 명령어의 입력으로 사용할 수 있다. awk 안에서 유닉스 명령과 인수를 사용하는 경우는 인용부호(" ")로 묶어서 사용한다.

$ cat ex09 
END { print " Pipe Test ...Is it OK? " | "mail guest" } 

$ awk -f ex08 data1 
$ login guest 
Welcome to guest account 
You have mail 

8) 프로그래밍 언어 구조 제어문들

 

" if " 문

ex)
{ if ( $1 < 100 && $2 > $3 ) 
{ print "첫번째 필드값이 100보다 작고 두 번째 필드값이 세 번째 필드값 보다 큽니다" } 
}

ex) 
{ if ( $1 > 100 || $2 >100 ) 
{ print "첫번째 필드값이 100보다 크거나 두 번째 필드값이 100보다 큽니다" } 
}

 

" while " 문

{ i = 1 
while ( i <= NF ) 
{ print "필드수가 1개보다 작거나 같습니다" } 
}

 

" for " 문

ex) 
$ cat ex10 
{ for ( a = 1 ; a <= NF ; a++ ) print NR,a ,$a } 
$ awk -f ex10 data1 
1 1 100 
1 2 200 
2 1 300 
2 2 400 
3 1 500 
3 2 600 
$

 

" break "문은 순환문의 수행을 중지 시키고 순환문 밖의 문장을 수행한다


" continue "문은 순환문의 수행을 중지하고, 순환문의 처음 조건을 테스트한다.


" next " 문은 다음 입력 레코드를 읽어 들이고 프로그램 수행은 패턴문의 처음을 수행한다.


" exit " 문은 프로그램 실행을 종료한다

 

ex) 
$ cat ex11 
{ for ( n = 1; ; n++ ) 
{ if ( n <= NF ) { print NR, n, $n 
  continue } 
  break 
} } 

$ cat ex12 
NF > 2 { print NR, NF; next } 

$ cat ex13 
$1 > 100 { print NR, " $2= ", $2, "$2값 오류" 
exit 99 } 
$

 

9) awk에서 많이 사용되는 함수들

 

" length " 함수는 주어진 문자열의 문자 개수를 반환한다. length 함수에 인수가 없으면 현재 입력 레코드의 문자수를 반환한다.

$ cat ex14 
{ print NR, "입력된 문자열의 문자수는 " , length, "개입니다" } 
$

$ cat ex15 
{ print NR, "첫번째 필드의 문자수는 ", length($1), "개입니다" } 
$

 

" substr " 함수는 지정한 문자열에서 원하는 개수 만큼의 문자들을 추출하여 반환한다

$ cat ex16 
BEGIN { 
print substr("Happy Birthday",7,9) 
exit }

$ awk -f ex16 
Birthday

 

" index " 함수는 문자열에서 지정하는 문자열이 있는 위치를 나타낸다. 문자열에서 지정한 문자열이 포함되어 있지 않은 경우는 0 값을 반환한다.

$ cat ex17 
BEGIN { 
print index("Hello This is Kim","This") 
exit 
}

$ awk -f ex17 

$

 

" sprintf " 함수는 printf함수와 사용방법이 유사하지만 출력의 방향이 지정연산자의 왼편에 있는 변수명이다.

$ cat ex18 
{ var = sprintf("출력연습 : 첫 번째 필드 : %d ",$1) 
print var 

$

$ awk -f ex17 data1 
100 
300 
500 
$

 

3. sed

 

sed는 stream editor의 약어이며 문자를 스트림으로 나타나는 입력을 수정하거나 편집하는데 사용되는 툴입니다. 유닉스에서 제공하는 다른 편집기와의 차이점은 원본 파일을 변경시키지 않고 명령이 실행 되는 필터 기능을 가지고 있는 것입니다. 그래서 변경된 내용을 보존하기 위해서는 적절한 조치가 필요합니다.

1)   "sed" 명령어 실행 형식

sed [-n][-e edit_command][-f command_file][ input_data_files ..] 

옵션:
-n     결과행의 출력을 하지 않는다 
-e     편집할 명령을 기술한다. 각각의 편집 명령마다 이 옵션을 붙인다 
-f     편집할 명령을 파일로 작성한 뒤 파일에서 읽어서 명령을 실행한다 
input_data_file     입력을 지정하지 않으면 표준입력으로부터 입력을 읽어 들인다.

 

사용 형식 예제:

$ sed -e 'sed_command' -e 'sed_command' .... filenames 
$ sed -f sed_script_file filenames 
$ cat datafile 
Hello this is kim. 
I'm so happy to meet you. 
Test sample 
sample program 
Java programming

 

2) 라인 선택 출력과 파일로 출력

 

라인을 선택하여 출력할때는 -n 옵션과 sed명령중 p 명령을 이용하여 구현할 수 있다.

$ sed -n '1,3p' datafile <-- 1번-3번라인까지 출력한다. 
Hello this is kim. 
I'm so happy to meet you. 
Test sample 
$ sed -n '/^s/p' datafile 
sample program : 라인의 시작이 's'인 라인을 출력 
$ sed '/^s/p' datafile 
Hello this is kim. 
I'm so happy to meet you. 
Test sample 
sample program 
Java programming

$ sed -e '/^sample/w sam_file' datafile 
$ cat sam_file

sample program

 

3) 삭제, 추가, 삽입, 치환

 

삭제예
$ sed '1,3d 'datafile 
sample program 
Java programming 
$ sed '/^sample/,/^Java/d' datafile : 라인중 sample로 시작하는 라인 부터 Java로 시작하는 라인 까지 삭제
Hello this is kim.         
I'm so happy to meet you. 
Test sample

 

추가예
$ cat file1         : 각 라인의 아래에 '=====' 라인이 추가된다 

a\ 
===== 
$ sed -f file1 datafile 
Hello this is kim. 
===== 
I'm so happy to meet you. 
===== 
Test sample 
===== 
sample program 
===== 
Java programming 
=====

 

삽입예            : 각 라인 위에 '***' 라인이 추가된다
$ cat file2 
i\ 
*** 
$ sed -f sed_script_file filenames 
*** 
Hello this is kim. 
*** 
I'm so happy to meet you. 
*** 
Test sample 
*** 
sample program 
*** 
Java programming

 

치환예
$ sed -n '1,3s/t/T/gp' datafile         :변경된 라인만 출력 
Hello This is kim. 
I'm so happy To meet you. 
TesT sample 

$ sed '1,3s/t/T/g' datafile             :모든라인을 모두 출력 
Hello This is kim. 
I'm so happy To meet you. 
TesT sample sample program 
Java programming 

$ sed -n '1,3s/t/T/gw sam_file2' datafile     : 변경된 라인만 sam_file2 파일에 저장 한다 
$ cat sam_file2 
Hello this is kim. 
I'm so happy To meet you. 
TesT sample 

$ sed 's/\/export\/home/\home3/g']

'/' 문자는 '\'문자를 사용하여 표시한다. 
/export/home is user01's base directory <-- 입력라인 
/home3 is user01's base directory <- 출력라인

블로그 이미지

오픈이지

시큐어코딩 교육/컨설팅 전문가 그룹

댓글을 달아 주세요