정규식은 리눅스 유틸리티들이 텍스트를 필터를 할수 있게 사용자가 그 패턴을 정의해 주는 것을 말합니다.
아래 그림은 정규 표현식을 이용햇서 데이터가 필터링 되는 과정을 보여 줍니다.
예를 들어 "*' 문자는 패턴에 매치가 되는 모든 파일들을 리스트해 줍니다. 아래의 예제를 살펴 보도록 합니다.
$ ls -al da* -rw-r--r-- 1 ==> da로 시작하는 모든파일을 리스트업
-rw-r--r-- 1 rich rich 25 Dec 4 12:40 data.ts
-rw-r--r-- 1 rich rich 180 Nov 26 12:42 data1
-rw-r--r-- 1 rich rich 45 Nov 26 12:44 data2
-rw-r--r-- 1 rich rich 73 Nov 27 12:31 data3
-rw-r--r-- 1 rich rich 79 Nov 28 14:01 data4
-rw-r--r-- 1 rich rich 187 Dec 4 09:45 datatest
$
|
정규 표현식의 종류
정규 표현식을 사용하기에 불편한 점은 정규 표현식의 종류가 어플리케이션에 따라 종류가 많다는 것 입니다.
리눅스에서의 정규 표현식 엔진의 종류는 아래와 같이 두 가지가 있습니다.
■ BRE Engine: Posix기반의 정규 표현엔진
■ ERE: Posix의 확장도니 버전의 정규 표현 엔진
1. BRE 패턴 정의 하기
A. 평문 문자 필터링하는 방법은 다른 글에서 sed및 gawk 사용시 많이 사용을 해 왔습니다. 간단한 예제를 하나 살펴 보도록 하겠습니다.
$ echo "This is a test" | sed -n ’/test/p’ ==> test 패턴에 맞는 행이 출력이 됩니다.
This is a test
$ echo "This is a test" | sed -n ’/trial/p ==> trial 에 맞는 패턴을 찾았지만 맞는 행이 없어서 출력이 없음.
$
|
평문 텍스트 패턴을 정의할때 주의할 점을 살펴 보겠습니다. 우선 정규 표현식은 대소문자를 구별 합니다.
BRE패턴 정의는 찾는 문자 패턴이 어디에 있던 상관이 없이 매치가 되면 출력을 합니다. 아래 예를 한번 살펴 보겠습니다.
$ echo "The books are expensive" | sed -n ’/book/p’ => 앞에서 부터 books중 book가 매치 되므로 출력
The books are expensive
$
위의 예제를 반대로 해보면
$ echo "The book is expensive" | sed -n ’/books/p’ => books 패턴으로 찾지만 s가 매치 되지 않아 미 출력
$
|
정규 표현식에서는 숫자와 space도 포함을 할수가 있습니다.
$ echo "This is line number 1" | sed -n ’/ber 1/p’ ==> ber 1이 매치가 되어 출력이 됨
This is line number 1
$
이번에는 space를 제외를 하고 조회를 해보면 출력이 되지 않습니다. space도 문자로 취급이 됩니다.
$ echo "This is line number1" | sed -n ’/ber 1/p’
$
|
특수문자 처리
정규 표현식에서는 미리 그 뜻이 정의 되어 있는 몇개의 특수문자를 문자 패턴으로써 사용을 하지 못합니다.
그런 특수 문자들을(.*[]^${}\+?|()) 문자 패턴으로 사용을 하려면 특수 문자 앞에 백슬러쉬를 상용하여 표시를해주어야 합니다. 예제를 몇개 살펴 보도록 하겠습니다.
$ cat data2
The cost is $4.00
$ sed -n ’/\$/p’ data2 The cost is $4.00 $ ==> $패턴을 사용하기 위해 $앞에 \처리를 합니다.
$ echo "\ is a special character" | sed -n ’/\\/p’ ==>백슬러쉬를 찾기 위해 앞에 \ 문자를 붙입니다.
\ is a special character $
슬러쉬를 검색하기 위한 예제 입니다.
$ echo "3 / 2" | sed -n ’/\//p’ 3/2
$
|
Anchor 문자 사용하기
정규 표현식에서는 시작과 끝을 나타내는 특수문자가 있습니다. 그 중 탈자 문자(^)는 텍스라인의 시작을 알리는 특수 문자 입니다 아래 예제를 보도록 하겠 습니다.
라인의 시작 부분 검색 하기
$ echo "The book store" | sed -n ’/^book/p’ => 라인의 시작이 book로 시작하는 문장 검색
$
$ echo "Books are great" | sed -n ’/^Book/p’ => 라인의 시작이 Book로 시작하는 라인 검색
Books are great
$
$ cat data3
This is a test line.
this is another test line.
A line that tests this feature.
Yet more testing of this
$ sed -n ’/^this/p’ data3 ==> 라인의 시작이 this로 시작하는 라인 검색
this is another test line.
$
|
라인의 마지막 부분 검색 하기
탈자 부호(^)와는 반대로 라인의 마지막을 검색할때 사용하는 툭수 문자는 '$' 문자 입니다. 아래 몇가지 예를 통해서 사용하는 방법을 알아 보도록 하겠 습니다.
$ echo "This is a good book" | sed -n ’/book$/p’ ==> 라인의 마지막에 book이 있는 라인 검색
This is a good book
$ echo "This book is good" | sed -n ’/book$/p’ ==> 라인의 마지막에 book이 없어서 미 출력
$
|
시작문자와 끝문자 함께 사용하기
탈자 부호 ^와 라인의 마지막을 나타내는 $ 기호를 사용해서 원하는 부분을 검색할 수도 있습니다.
아래 몇개의 유용한 사용 예제를 살펴 보도록 하겠습니다.
$ cat data4
this is a test of using both anchors
I said this is a test
this is a test
I’m sure this is a test.
$ sed -n ’/^this is a test$/p’ data4 ==> this is a test로 정확히 매치 되는 부분만 출력
this is a test
$
위의 예에서 보듯이 시작 부호 ^와 마지막 문자 $를 함깨 사용하면 매치 되는 부분만 출력을 하고 같은 라인의 다른 부분들은 무시가 됩니다.
$ cat data5
This is one test line.
This is another test line.
$ sed ’/^$/d’ data5 ==> 시작과 끝에 아무런 패턴을 넣지 않음
This is one test line.
This is another test line.
$
파일에서 공백인 라인을 찾아서 sed의 삭제 명령어인 d를 이용하여 공백 라인을 삭제를 합니다.
|
dot 문자 이용하기
dot(.) 특수 기호는 정규 표현식에서 한개의 문자를 의미 합니다 아래 사용 예제를 살펴 보도록 합시다.
$ cat data6
This is a test of a line.
The cat is sleeping.
That is a very nice hat.
This test is at line four.
at ten o’clock we’ll go home.
$ sed -n ’/.at/p’ data6 ==> at으로 끝나는 문자의 길이가 3개인 문자를 검색
The cat is sleeping. ==. cat
That is a very nice hat. ==> hat
This test is at line four. ==>공백at
$
여기서 특이한 점은 dot 특수 문자는 공백도 한개의 문자로 취급을 하고 있다는 점을 기억 하시면 될것 같습니다.
|
Character classes 사용하기
캐릭터 클래스는 특정 문자들을 매치 시키고 싶을때 사용할수 있습니다. 사용방법은 대괄호 안에 매치 시킬 패턴들을 넣어 사용하시면 됩니다. 아래 예를 살펴 보겠습니다.
$ sed -n ’/[ch]at/p’ data6 ==> at으로 끝난느 단어중 앞 문자가 c나 h인 라인을 출력.
The cat is sleeping.
That is a very nice hat.
$
단어다 대문자로 시작할지 소문자로 시작할지 모를때 사용하는 예제 입니다.
$ echo "Yes" | sed -n ’/[Yy]es/p’
Yes
$ echo "yes" | sed -n ’/[Yy]es/p’ yes
$
하나 이상의 캐릭터 클래스를 사용하는 예제
$ echo "Yes" | sed -n ’/[Yy][Ee][Ss]/p’
Yes
$ echo "yEs" | sed -n ’/[Yy][Ee][Ss]/p’
yEs
$ echo "yeS" | sed -n ’/[Yy][Ee][Ss]/p’
yeS
$
charecter class에 숫자 사용 예제
$ cat data7
This line doesn’t contain a number.
This line has 1 number on it.
This line a number 2 on it.
This line has a number 4 on it.
$ sed -n ’/[0123]/p’ data7
This line has 1 number on it.
This line a number 2 on it.
$
다섯자리 숫자패턴 찾기
$ cat data8
60633
46201
223001
4353
22203
$ sed -n ’ >/[0123456789][0123456789][0123456789][0123456789][0123456789]/p >’ data8 60633 46201 223001 22203
$
$ cat data9
I need to have some maintenence done on my car.
I’ll pay that in a seperate invoice.
After I pay for the maintenance my car will be as good as new.
두개의 패턴에 매치된느 문장 찾기.
$ sed -n ’ /maint[ea]n[ae]nce/p
/sep[ea]r[ea]te/p ’ data9
I need to have some maintenence done on my car.
I’ll pay that in a seperate invoice.
After I pay for the maintenance my car will be as good as new.
$
|
Negating character classes 사용하기
character classes의 사용과 반대로 캐릭터 클래스에 매치 되지 않는 문자를 찾을때에는 탈자 부호(^)를 패턴의 맨 앞줄에 입력을 하면 캐릭터 클래스에 매치 되지 않는 라인들을 찾을 수 있습니다.
$ sed -n ’/[^ch]at/p’ data6 ==> c와 h로 시작하지 않는 at 문자열 출력
This test is at line two.
$
|
범위 사용하여 검색하기
캐릭터 클래스에서 '-' 기회를 사용하여 검색할 범위를 지정할 수가 있습니다.
$ sed -n ’/^[0-9][0-9][0-9][0-9][0-9]$/p’ data8 ==> 숫자로 시작하는 5자리 숫자 라인 검색
60633
46201
45902
$
$ sed -n ’/[c-h]at/p’ data6 ==. c와 h사이의 문자중 at으로 끝나는 라인 검색
The cat is sleeping.
That is a very nice hat.
$
$ sed -n ’/[a-ch-m]at/p’ data6 ==> a에서 c나 h그리고 h에서 m 사이의 문자중 at으로 끝나는 라인 검색.
The cat is sleeping.
That is a very nice hat.
$
|
BRE에서 제공하는 특수 문자 사용하기
BRE에서는 아래의 표와 같이 특수 문자를 정규식 표현에 사용을 하고 있습니다.
아래 예제와 표를 살펴 보도록 합시다.
$ echo "abc" | sed -n ’/[[:digit:]]/p’ ==> 숫자를 포함하는 라인 출력
$ $ echo "abc" | sed -n ’/[[:alpha:]]/p’ ==> 알파벳을 포함하는 라인 출력
abc
$ echo "abc123" | sed -n ’/[[:digit:]]/p’ ==> 숫자를 포함하는 라인 출력
abc123
$ echo "This is, a test" | sed -n ’/[[:punct:]]/p’ ==> 마침표를 포함하는 라인 출력
This is, a test
$ echo "This is a test" | sed -n ’/[[:punct:]]/p’ ==> 마침표를 포함하는 라인 출력.
$
|
BRE 특수 문자 캘릭터 클래스
아래는 자주 사용하는 캐릭터 클래스를 모아 놓은 표 입니다 참고 하시기 바랍니다.
The asterisk 사용하기
'*'문자는 특정 문자사이에 올때 그 사이에서 최소 0번 이나 여러개의 문자를 매치 시킬때 사용할 수가 있습니다.
아래 예제를 살펴 보도록 하겠 습니다.
$ echo "ik" | sed -n ’/ie*k/p’ ==> 별표 앞의 e는 나타나지 않을 수도, 여러번 나타날수 있스니다.
ik
$ echo "iek" | sed -n ’/ie*k/p’
iek
$ echo "ieek" | sed -n ’/ie*k/p’
ieek
$ echo "ieeek" | sed -n ’/ie*k/p’
ieeek
$ echo "ieeeek" | sed -n ’/ie*k/p’
ieeeek
$
$ echo "bt" | sed -n ’/b[ae]*t/p’ ==> a나 e문자가 나타날수도 나타나지 않는 t로 끝나는 라인 검색
bt
$ echo "bat" | sed -n ’/b[ae]*t/p’
bat
|
Extended Regular Expressions 사용 하기
The question mark'?' 도 별표와 비슷하게 사용 가능 합니다. 다만 틀린 점은 '?' 마크는 별표와는 다르게 여러개의 문자를 매치 하기는 않고 한개의 문자만 매치를 시킵니다. 다시말해 해당 문자 1글자가 나타나는 라인이나 포함되지 않는 라인을 검색을 합니다. 아래 예를 살펴 보도록 하겠 습니다.
$ echo "bt" | gawk ’/be?t/{print $0}’ ==> e가 나타나지 않는 라인 출력
bt
$ echo "bet" | gawk ’/be?t/{print $0}’ ==> e가 한번 나타나는 라인 출력
bet
$
$ echo "beet" | gawk ’/be?t/{print $0}’ ==> e가 2번 나타나서 제외
$ $ echo "beeet" | gawk ’/be?t/{print $0}’ ==> e가 3번 나타나서 제외
$
|
The plus sign 사용하기
플러스 캐릭터'+' 특수 문자는 패턴에서 플러스 캐릭터 앞의 문자가 최소 한번 이상 나오는 라인들을 검색 해서 출력을 해 줍니다. 즉 + 특수 문자 앞에 있는 문자가 없는 라인은 검색 되지 않습니다.
아래의 예제를 살펴 봅시다.
$ echo "beeet" | gawk ’/be+t/{print $0}’ beeet
$ echo "beet" | gawk ’/be+t/{print $0}’ beet
$ echo "bet" | gawk ’/be+t/{print $0}’ bet
$ echo "bt" | gawk ’/be+t/{print $0}’
$
|
증괄호를 사용해 매치된는 문자의 횟수 지정하기.
증괄호를 사용하여 중괄호 앞에 매치된는 문자의 반복 횟수를 지정을 할수가 있습니다. 번호 지정 하는 방법은 아래와 같이 2가지 경우가 있습니다.
■ m: m번째 나타나는 라인을 검색
■ m,n: 최소 m번 최대 n번 매치되는 라인 검색.
※ gawk 에디터는 기본적으로 정규식 표현 inteval을 인식하지 못합니다. 그래서 인식을 시키기 위해 아래 예제 처럼 --re-interval 명령을 입력후에 사용을 해야 합니다.
$ echo "bt" | gawk --re-interval ’/be{1}t/{print $0}’ $ ==> e문자가 1번만 나타나는 라인 검색
$ echo "bet" | gawk --re-interval ’/be{1}t/{print $0}’
bet
$ echo "beet" | gawk --re-interval ’/be{1}t/{print $0}’
$
$ echo "bt" | gawk --re-interval ’/be{1,2}t/{print $0}’ ==> e가 최소 한번 최대 2번 나타나는 라인 검색
$ $ echo "bet" | gawk --re-interval ’/be{1,2}t/{print $0}’
bet
$ echo "beet" | gawk --re-interval ’/be{1,2}t/{print $0}’
beet
$ echo "beeet" | gawk --re-interval ’/be{1,2}t/{print $0}’
$
케릭터 클래스 안에서 interval 사용하기
$ echo "bt" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
==> b로 시작하고 a나 e가 1번이나 2번 나타나는 라인 검색
$
$ echo "bat" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
bat
$ echo "bet" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
bet
$ echo "beat" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
beat
$ echo "beet" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
beet
$ echo "beeat" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
$
$ echo "baeet" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
$
$ echo "baeaet" | gawk --re-interval ’/b[ae]{1,2}t/{print $0}’
$
|
The pipe symbol 사용하기
파이프'|' 기호를 사용하여 정규 표현식을 여러개 연결을 하면 or 효과를 볼수가 있습니다. 조건 중 하나만 매치가 되면 그 라인을 출력해 줍니다.
$ echo "The cat is asleep" | gawk ’/cat|dog/{print $0}’
The cat is asleep
$ echo "The dog is asleep" | gawk ’/cat|dog/{print $0}’
The dog is asleep
$ echo "The sheep is asleep" | gawk ’/cat|dog/{print $0}’
|
Grouping expressions 사용하기
소괄호를 사용하여 여러개의 문자를 묶어서 하나의 문자로 취급하게 할수가 있습니다. 아래의 예제를 살펴 보도록 합니다.
$ echo "Sat" | gawk ’/Sat(urday)?/{print $0}’ ==> (urday)가 나타나거나 나타나지 않는 라인 출력
Sat
$ echo "Saturday" | gawk ’/Sat(urday)?/{print $0}’
Saturday
$
파이프와 함께 사용하는 예제
$ echo "cat" | gawk ’/(c|b)a(b|t)/{print $0}’ => c나b로 시작하고 a뒤의 문자가 b나 t인 라인 검색
cat
$ echo "cab" | gawk ’/(c|b)a(b|t)/{print $0}’
cab
$ echo "bat" | gawk ’/(c|b)a(b|t)/{print $0}’
bat
$ echo "bab" | gawk ’/(c|b)a(b|t)/{print $0}’
bab
$ echo "tab" | gawk ’/(c|b)a(b|t)/{print $0}’
$
$ echo "tac" | gawk ’/(c|b)a(b|t)/{print $0}’
$
|
정규 표현식 실 사용 예제 살펴 보기
리눅스 환경변수 중 PATH경로에 있는 모든 경로들의 파일 갯수를 카운터 하는 스크립트를 살펴 보겠습니다.
#!/bin/bash
# count number of files in your PATH
mypath=`echo $PATH | sed ’s/:/ /g’` ==> PATH변수값에서 ':'을 ' ' 공백으로 바꾸어 mypath에 저장
count=0 ==.>count변수를 0으로 초기화
for directory in $mypath ==> for문으로 mypath에 저장된 경로들을 순회 검색
do
check=`ls $directory` ==> mypath에서 directory변수로 전달된 디렉토리 검색
for item in $check
do
count=$[ $count + 1 ] ==> check변수에 저장된 아이템들의 갯수를 카운팅
done echo "$directory - $count" ==> 디렉토리 값과 카운트 값 출력
count=0 ==> 다른 경로 탐색을 위해 카운트값 초기화.
done
$ ./countfiles
/usr/local/bin - 79
/bin - 86
/usr/bin - 1502
/usr/X11R6/bin - 175
/usr/games - 2
/usr/java/j2sdk1.4.1 01/bin - 27
$
|
두번째 전화번호 유효성 검사 하기
#!/bin/bash
# script to filter out bad phone numbers
gawk --re-interval ’/^\(?[2-9][0-9]{2}\)?(| |-|\.) [0-9]{3}( |-|\.)[0-9]{4}/{print $0}’
$
패턴을 해석을 해보면
^\(? ==> 라인의 시작이 괄호'('로 시작하거나 시작하지 않거나.
[2-9][0-9]{2} 2에서 9사이의 숫자 1개와 0에서 9사이의 숫자 2개
\)? 닫기 괄호로 매치 되거나 되지 않거나.
( |-|\.) ==> 공백이거나 '-'이거나 dot'.' 이고
[0-9]{3} ==> 0에서 9사이의 숫자 3자리
}( |-|\.) ==> 공백이거나 '-'이거나 dot'.' 이고
[0-9]{4} ==> 0에서 9사이의 숫자 4자리
|
Parsing an e-mail address
현대의 거의 모든 업무가 메일을 통해 이루어 지고 있고 이런 메일 주소의 유효성을 검사하는것도 하나의 중요한 일이 되었습니다. 아래의 스크립트는 이메일의 유효성을 확인해 볼수 있는 정규 표현식을 정리 하였습니다.
보통 이메일 주소는 아래와 같이 username 부분과 hostname부분으로 분리가 되고 각각의 필드에서 유효한 특수 문자들은 아래와 같습니다.
username의 유효한 특수 문자
■ Dot
■ Dash
■ Plus sign
■ Underscore
hostname의 유효한 특수 문자
■ Dot
■ Underscore
자 아제 아래 정규 표현식 예제를 살펴 봅시다.
^([a-zA-Z0-9 \-\.\+]+)@^([a-zA-Z0-9 \-\.\+]+)
@로 분리되는 username 정규 표현식을 살펴 보겠습니다.
^([a-zA-Z0-9 \-\.\+]+) ==> 라인의 시작이 a~z사이의 소문자나, A~Z사이의대문자, 또는 0~9까지의 숫자나, '-','.','+기호들의 조합이 1번 이상('+' 문자) 나타나는 라인을 검색
이후 도메인 및 서버명을 나타내는 뒷부분의 표현식을 보면.
^([a-zA-Z0-9 \-\.\+]+)
==> 시작은 소문자 a~z이거나 대문자 A~Z이거나 숫자 0~9번사이의 숫자와 '-','/','+' 기호가 나오는 문자열 검색
|
그 밖에 다양한 정규 표현식을 사용하여 입력데이터의 유효성을 검색할수도 있고, 정말 정규 표현식은 리눅스 세계에서는 반드시 알아야 하는 표현식 입니다.
그럼 열공 하시고 다음에 다시 포스팅 하도록 하겠 습니다.
'쉘스크립트' 카테고리의 다른 글
Advance gawk (0) | 2022.07.06 |
---|---|
진화된 sed (1) | 2022.07.06 |
sed와 gawk의소개 (2) | 2022.07.06 |
스크립트에서 그래픽 사용하기 (1) | 2022.07.06 |
함수 만들기 (1) | 2022.07.06 |