정규표현식이란 텍스트에서 패턴을 인식하는 symbol 표기법
grep
- grep [옵션] [패턴] [파일]
- 파일에서 지정된 정규표현식과 일치하는 행을 찾아 출력한다.
옵션
- i : 대소문자 구분안함, --ignore-case
-v : 반전 매치, invert-match
-c : 정규표현식에 매치하는 행의 수 출력, --count
-l : 일치하는 행을 포함하는 파일의 이름을 출력, --files-with-mathces
-L : 일치하는 행이 없는 파일의 이름을 출력, --files-without-matches
-n : 일치하는 행 앞에 파일의 행 번호를 붙여 출력, --line-number
-h : 복수 파일 검색에서, 파일명을 출력에서 숨김, --no-filename
기본 예문 )
1. grep으로 root 라는 문장을 /etc/passwd에서 찾아내기
grep root /etc/passwd
# grep jwchoi /etc/passwd
jwchoi:!:720:700::/ofm/jwchoi:/usr/bin/ksh
2. grep으로 파이프를 삽입해 zip이 포함된 문자열을 찾는다.
ls /usr/bin | grep zip
ls /usr/bin | grep zip
[node1@jwchoi:/ofm/jwchoi/sw2/tp/tuxedo12.2.2.0.0/samples/atmi/simpapp]# ls /usr/bin | grep zip
bunzip2
bzip2
bzip2recover
funzip
funzip_32
funzip_64
gunzip
gzip
unzip
unzip_32
unzip_64
unzipsfx
unzipsfx_32
unzipsfx_64
zipdetails
zipgrep
zipgrep_32
zipgrep_64
zipinfo
zipinfo_32
zipinfo_64
정규표현식 = Literal (상수문자) + 메타문자
메타문자 -> ^ $ . [] - () \ | ? * + {}
주의해야할 점 : 메타문자는 쉘의 확장에 사용되므로, 확장 방지를 위해 메타문자를 따옴표로 묶어야한다.
1) 앵커 메타문자 : ^ (행의 시작을 나타낸다) , $ (행의 끝을 나타낸다)
[node1@jwchoi:/ofm/jwchoi/sw2/tp/tuxedo12.2.2.0.0/samples/atmi/simpapp]# ls /usr/bin > dirlist-usr-bin.txt
[node1@jwchoi:/ofm/jwchoi/sw2/tp/tuxedo12.2.2.0.0/samples/atmi/simpapp]# ls /sbin > dirlist-sbin.txt
[node1@jwchoi:/ofm/jwchoi/sw2/tp/tuxedo12.2.2.0.0/samples/atmi/simpapp]# ls /usr/sbin > dirlist-usr-sbin.txt
[node1@jwchoi:/ofm/jwchoi/sw2/tp/tuxedo12.2.2.0.0/samples/atmi/simpapp]# ls dir*
dirlist-bin.txt dirlist-sbin.txt dirlist-usr-bin.txt dirlist-usr-sbin.txt
출력된 텍스트 문서로 테스트 진행
grep -h '^pas' dirlist*.txt
- 행시작이 'pas'로 시작되는 것을 dirlist들의 파일 안에서 내용을 찾아달라는 명령.
- -h는 복수파일에서 찾아달라는 옵션.
grep -h 'zip$' dirlist*.txt
- 문장의 끝이 zip으로 끝나는 것을 찾아달라는 명령어.
grep -h '^zip$' dirlist* .txt
- 메타문자 ^,$를 둘다 입력한다면 출력되지않음.
- 정확한 검색명을 입력해야하만 출력이 이루어진다.
2) 모든 문자
[.] 을 사용하게 되면 어떤 문자든 일치시킨다는 의미다.
옵션은 그대로 -h를 주고,
grep -h '.user' dirlist*.txt
를 입력하게되면 user가 포함된 문자는 모두 출력된다.
# grep -h '.user' dirlist*.txt
chuser
mkuser
ruser
rusers
chuser
mkuser
ruser
rusers
fuser
listusers
lsuser
rmuser
3) 대괄호[] 표현식과 문자클래스
대괄호 안에 놓인 메타문자는 특수 의미가 사라진다.
하지만 대괄호 안의 ^는 부정이 되고, -는 문자 범위를 의미하게 된다.
ex) grep -h '[rm]user' dirlist*.txt
이 문형의 같은 경우에는 대괄호를 풀어 해석하면 'ruser'나 'muser'를 포함하는 행을 출력해달라는 의미이다.
사용을 해보면 r과 m이 포함된 파일 내 값이 출력되는 것을 확인할 수 있다.
# grep -h '[rm]user' dirlist*.txt
ruser
rusers
ruser
rusers
rmuser
ex2) 그럼 [rm] 내에 ^를 포함해서 '[^dw]user'를 검색해보면 어떻게 될까?
부정이 된다했다.
그렇다면 'ruser'나 'muser'는 포함되지 않아야한다.
그렇다.
# grep -h '[^rm]user' dirlist*txt
chuser
mkuser
chuser
mkuser
fuser
listusers
lsuser
ex3) 세번째는 문자범위이다. 문자 범위는 아까 설명과 같이 [-]로 표현할 수 있다고 했는데 예문을 보자.
grep -h '^[A-Z]' dirlist*.txt 를 입력해보자.
*주의사항으로는 여기서 ^는 대괄호 밖에 있으므로 부정표현이 아니라 A-Z까지의 내용중 대문자로 시작하는 내용을 출력하라 라는 뜻이다.
# grep -h '^[A-Z]' dirlist*.txt
DEFLT_C
DEFLT_CPP
IbDebugChk
IbDebugOff
IbDebugOn
Mail
ManGetURL.class
Rsh
SpmiArmd
SpmiResp
X11
X11r5
X11r6
DEFLT_C
DEFLT_CPP
IbDebugChk
IbDebugOff
IbDebugOn
Mail
ManGetURL.class
Rsh
SpmiArmd
SpmiResp
X11
X11r5
X11r6
IbDebugChk
IbDebugOff
IbDebugOn
ex4) grep -h '[A-Za-z0-9]' dirlist*.txt
: 영대문자, 영소문자, 숫자 0~9까지를 포함하는 모든 내용을 출력하라
.
.
.
.
.
varyoffvg
varyonvg
virtiostat
vmmgr
vmo
vpdadd
vpddel
wall
watch
which_fileset
whodo
wlmassign
wlmcheck
wlmcntrl
wlmd
wlmstat
wol
wpar_drh
wparcpstat
wpardrd
wparerr
wparexec
wparmemstat
wparprnterr
wparvpid2pid
writesrv
xntpd
xntpdc
yearistype
ypset
zdump
zic
POSIX 문자클래스
[:alpha:] 알파벳 영대소문자를 의미. [A-Za-z]
[:alnum:] 알파벳과 숫자를 의미. [A-Za-z0-9]
[:digit:] 숫자 0~9를 의미. [0-9]
[:xdigit:] 16진수 숫자를 의미. [0-9A-Fa-f]
[:lower:] 영소문자를 의미. [a-z]
[:upper:] 대소문자를 의미. [A-Z]
[:blank:] 스페이스와 탭 문자를 의미. [\t]
[:space:] 공백문자, 스페이스, 탭, 개리지리턴, 수직탭, 폼피드를 의미한다. [\t\r\n\v\f]
간단한 예.
ex)
grep '^[[:upper:]]' dirlist*.txt : 대문자로 시작하는 행을 찾는 것임.
grep '^[[:lower:]]' dirlist*.txt : 소문자로 시작하는 행을 찾는 것임.
Alternation 정규식 확장기능
파이프 [ | ] 를 이용하여 확장 정규표현식을 사용한다.
echo "AAA" | grep AAA
에코 기능을 이용해 AAA를 사용하였을 때 grep 에서 AAA를 받아보고 일치하면 출력시켜주는 내용.
echo "AAA" | grep -E 'AAA|BBB'를 하게 되면 어떻게 될까?
AAA거나 BBB인 것이 에코입력에서 일치하게되면 출력해준다.
옵션 -E는 확장 정규표현식 사용옵션을 나타내주는 것이다. 이것을 빼버리면 출력이 되지않는다.
CCC 나 DDD를 입력하면 당연히 출력되지 않을 것이다.
# echo "AAA" | grep -E 'AAA|BBB'
AAA
# echo "BBB" | grep -E 'AAA|BBB'
BBB
# echo "BBB" | grep 'AAA|BBB'
ex3) grep 'Eh '^(gz|dw)' dirlist*.txt
이건 Alternation과 다른 정규표현식 요소와 결합할 때 사용할 수 있는 응용이다.
확장 정규표현식으로 [-E] 도 쓰고 [-h]도 써줌으로써 아까 많이 출력해놨던 복수파일을 실행해본다.
: 해당 문자열로 시작되는 파일을 검색해 출력해준다!
# grep -Eh '^(gz|dw)' dirlist*.txt
gzexe
gzip
gzexe
gzip
수량 한정자 (확장 정규표현식 기능) : ?, *, +, {}
? : (앞의 항목이 없거나 한번만 나타남) 앞의 요소는 선택적이라는 의미이다.
ex) 전화번호로 예를 들면, (000)- 000- 0000 또는 0000 0000-0000이라는 양식을 가지는 전화번호가 있다고생각해보자.
정규식은 ^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$로 정의할 수 있다.
저기서, 괄호를 문자로 표기할 때는 앞에 \ 기능을 이용해 표시해주어야 한다. 해석을 하면 일단 [0-9]는 숫자 한자리가 되는건데, 앞의 항목이 없거나 한번만 나타나는 것을 의미하거나 선택적이라는 의미를 나타내는 의미에서 [?]를 쓴다.
그래서 괄호 또는 문자 뒤에다 ?를 붙여주면 저게 있어도 되고~ 없어도 된다~ 라는 뜻으로 해석되게 된다.
테스트!
echo "(070) 123-4567" | grep -E '^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$'
(070) 123-4567
echo "070 123-4567" | grep -E '^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$'
070 123-4567
괄호가 없어도 출력이 된다.
다만 저 양식에서 더 벗어나면 출력이 되지 않는다. 앞에 엉뚱한 문자가 와있거나 전화번호가 총 10자리가 아니거나 하는 경우에는 출력이 되지 않을 것이다.
* : 앞 항목이 없거나 여러번 되는 것을 의미한다.
ex) 대문자 하나, 여러 대소문자와 공백을 포함하는 문자열의 정규표현식.
[[:upper:]][[:upper:]][lower:] ]* 이 식을 짚어보자면 괄호를 잘 보면 된다.
첫번째가 대문자, 그뒤부터는 대소문자가 오는 모든 문자라고 해석해볼 수 있다.
lower POSIX 뒤에 띄어쓰기가 들어가있어야 꼭 띄어쓰기를 인식해 출력한다.
아니면 모든 문자를 붙여써야한다...
그래서,
echo "This works." | grep -E '[[:upper:]][[:upper]][:lower:] ]*\.' 를 사용해보면,
This works.
정상적으로 출력된다.
되지 않는다면 POSIX 뒤에 띄어쓰기가 꼭 있는지, POSIX는 제대로 썼는지, 또 저 정규식을 쓴다면 대문자로 시작이 되고 있는지 확인해보시고 출력을 다시 해보자.
+ : 앞 항목이 한번 이상되는 것을 의미한다.
ex) 단일 스페이스로 구분된 하나 이상의 알파벳으로 구성된 그룹을 찾는 정규표현식
^([[:alpha:]]+ ?)+$ 로 표현해볼 수 있다.
해석 : 모든 영소대문자를 포함해 공백이 포함되어있고 그것이 하나 이상이다. 그리고 시작이나 끝에 포함된다...
echo "haHa iCanDoThisAllDay" | grep -E '^([[:alpha:]]+ ?)+$'
haHa iCanDoThisAllDay
주의할 점은 영대소문자만 포함하는 문자이기 때문에 역시 숫자가 들어간다거나, 띄어쓰기가 한번만 포함되는 문자열이기 때문에 두번 띄어쓰기를 했다거나 하는 경우에는 조건이 부합하기 때문에 출력되지 않는 점을 유의하고 여러가지 시도를 해봐야한다.
{}: 앞 항목이 지정 횟수만큼 반복되어있는 것을 의미한다.
-{n} : 정확히 n번만 일치하는 선행 요소 검색
-{n,m} : 최소 n번, 하지만 m번 이하로 일치하는 선행 요소 검색
-{n,} : n번 이상 일치하는 선행 요소 검색
-{,m} : m번 이하 일치하는 선행 요소 검색
이러한 내용으로 보아 응용을 해보자니 아까 해봤던 ^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$ 이 기억이 나야한다.
계속 이렇게 써주던 걸 {}를 이용하면 편리하게 표현할 수 있다.
^\([0-9]{3}\)? [0-9]{3}-[0-9]{4}
이렇게 말인데... 엄청 쉬어진 것 같다...
echo "(070) 123-4567" | grep -E '^\(?[0-9]{3}\)? [0-9]{3}-[0-9]{4} $'
------
cat > phonelist.txt
(123) 123-4567
(234) 123-1231
(456) 454-4546
ctrl + c
로 나오고
테스트해보기
'OS > Linux&Unix' 카테고리의 다른 글
[Linux/Unix] find 명령어 / -mtime 옵션 - 일별로 파일 내용 확인하기 (0) | 2022.11.09 |
---|---|
[Linux/Unix] inode로 파일/디렉토리 삭제하기. inode 확인하기. (0) | 2022.11.08 |
[Linux/Unix] wc 명령어 - word count (0) | 2022.11.08 |
[Unix/Linux] AIX ftp 서비스 종료/시작 방법 (0) | 2022.11.08 |
[Linux/Unix] unix 파일 내용을 쉘 스크립트로 만들어서 보기 (0) | 2022.11.08 |