19장. 정규 표현식(Regular expressions)
- 차례
- 19.1. 정규 표현식의 간략한 소개
- 19.2. Globbing
- 19.1. 정규 표현식의 간략한 소개
쉘 스크립트를 완전하게 구사하기 위해서, 정규 표현식은 꼭 정복해야 합니다. 스크립트에서 자주 쓰이는 sed나 awk같은 명령어들이 정규 표현식을 사용합니다.
19.1. 정규 표현식의 간략한 소개
표현식(expression)이란 문자 그대로의 의미 이상으로 해석되는 메타문자(metacharacters)라고 부르는 문자들의 집합을 말합니다. 예를 들어, 인용 부호(quote symbol)는 어떤 사람이 말한 것을 나타내 주기도 하지만 또한 그 뒤에 나오는 심볼에 대해서 메타적 의미를 부여하기도 합니다. 정규 표현식은 유닉스에 특별한 특징을 부여하는 문자들과 메타문자들의 집합입니다. [1]
정규 표현식은 주로 텍스트 탐색과 문자열 조작에 쓰입니다. 정규 표현식은 하나의 문자와 일치(match)하거나, 혹은 문자열의 일부분(substring)이나 전체 문자열인 문자 집합들과 일치하게 됩니다.
-
별표(*)는 바로 앞의 문자열이나 정규 표현식에서 0개 이상 반복되는 문자를 나타냅니다.
"1133*" 은 11 + 하나 이상의 3 + 가능한 다른 문자들 을 나타냅니다: 113, 1133, 11312, 기타 등등.
-
점(.)은 뉴라인을 제외한 오직 한 개의 글자와 일치합니다. [2]
"13." 은 13 + 빈칸을 포함한 최소 한 글자 를 나타냅니다: 1133, 11333, 하지만 13은 뒤에 한 글자가 빠져 있기 때문에 아닙니다.
-
캐럿(^)은 줄의 시작을 나타내지만 가끔 문맥에 따라서는 정규 표현식에서 문자 집합의 의미를 반대로 해석해 줍니다.
-
정규 표현식의 제일 끝에 나오는 달러 표시($)는 줄 끝과 일치합니다.
"^$" 는 빈 줄과 일치합니다.
-
대괄호([...])는 단일 정규 표현식에서 표현하기 위해 문자들을 집합으로 묶어 줍니다.
"[xyz]" 는 x, y, z 중에 한 글자와 일치합니다.
"[c-n]" 는 c에서 n 사이에 들어 있는 한 문자와 일치합니다.
"[B-Pk-y]" 는 B에서 P까지 중이나 k에서 y까지 중의 한 글자와 일치합니다.
"[a-z0-9]" 는 소문자나 숫자중의 한 문자와 일치합니다.
"[^b-d]" 는 b에서 d사이의 문자를 제외한 모든 문자를 나타냅니다. ^은 바로 뒤에 나오는 정규 표현식의 의미를 반대로 해석하게 해 줍니다(다른 문맥에서 !의 의미와 비슷함).
여러개의 대괄호로 묶인 문자들은 일반적인 낱말 패턴을 나타냅니다. "[Yy][Ee][Ss]"는 yes, Yes, YES, yEs, 등등을 나타냅니다. "[0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]"는 주민등록번호와 일치합니다.
-
역슬래쉬(\)는 특수 문자를 원래의 문자 의미대로 해석하게 해줍니다(escape).
"\$" 는 정규 표현식에서 줄 끝(end-of-line)을 나타내는 의미대신 "$" 문자 그대로 해석하게 해줍니다. 비슷하게 "\\"는 그냥 "\" 문자 그 자체를 나타냅니다.
-
물음표(?)는 자기 앞에 나오는 정규 표현식이 0개나 한개인 것과 일치하고, 보통은 한 개의 문자와 일치할 때 쓰입니다.
-
더하기(+)는 자기 앞에 나오는 하나 이상의 정규 표현식과 일치합니다. *와 비슷하게 동작하지만 반드시 하나 이상과 일치합니다.
# GNU 버전의 sed와 awk에서는 "+"를 쓸 수 있지만, # 이스케이프(escape)를 해 줘야 됩니다. echo a111b | sed -ne '/a1\+b/p' echo a111b | grep 'a1\+b' echo a111b | gawk '/a1+b/' # 위의 세개는 모두는 동일합니다. # Thanks, S.C.
-
이스케이프된 "중괄호"(\{ \})는 바로 앞에 나온 정규 표현식의 빈도수를 나타냅니다.
중괄호를 이스케이프 시키지 않으면 중괄호 문자 그대로 해석되기 때문에 꼭 이스케이프를 시켜야 합니다. 이 방법은 기술적으로 볼 때, 기본적인 정규 표현식의 일부가 아닙니다.
"[0-9]\{5\}" 는 0에서 9까지의 문자가 정확히 5번 나오는 것을 나타냅니다.
경고 "전통적"인 awk에서는 중괄호를 정규 표현식으로 쓸 수 없습니다. 하지만, gawk에서 --re-interval을 주면 중괄호를 이스케이프 시키지 않고도 정규 표현식에서 쓸 수가 있습니다.
bash$ echo 2222 | gawk --re-interval '/2{3}/' 2222
-
소괄호인 ( )는 정규 표현식 그룹을 묶어줍니다. 다음에 설명할 "|" 연산자와 같이 쓰면 아주 좋습니다.
-
| "or" 정규 표현식 연산자는 가능한 문자들중 어떤 것과도 일치합니다.
bash$ egrep 're(a|e)d' misc.txt People who read seem to be better informed than those who do not. The clarinet produces sound by the vibration of its reed.
-
POSIX 문자 클래스(POSIX Character Classes). [:class:]
일치하는 문자의 범위를 지정하는 다른 방법입니다.
-
[:alnum:] 는 알파벳이나 숫자와 일치하고 [A-Za-z0-9] 와 같은 표현입니다.
-
[:alpha:] 는 알파벳과 일치하고 [A-Za-z] 와 같은 표현입니다.
-
[:blank:] 는 빈 칸이나 탭과 일치합니다.
-
[:cntrl:] 는 제어 문자들과 일치합니다.
-
[:digit:] 는 10진 숫자들과 일치하고 [0-9] 와 같은 표현입니다.
-
[:graph:] (출력가능한 그래픽 문자들). 아스키 33 - 126 의 문자들과 일치합니다. 빈 칸 문자가 포함되지 않는다는 것만 제외하고는 밑에서 설명할 [:print:] 와 같습니다.
-
[:lower:] 는 알파벳 소문자와 일치하고 [a-z] 와 같은 표현입니다.
-
[:print:] (출력 가능한 문자들). 아스키 32 - 126 까지의 문자들과 일치합니다. 위에서 설명한 [:graph:] 와 같지만 빈 칸 문자가 포함되어 있습니다.
-
[:space:] 는 공백문자들과 일치합니다(빈 칸, 수평탭).
-
[:upper:] 는 알파벳 대문자와 일치하고 [A-Z] 와 같은 표현입니다.
-
[:xdigit:] 는 16진수 숫자와 일치하고 [0-9A-Fa-f] 와 같은 표현입니다.
Sed, awk, 펄은 스크립트에서 정규 표현식을 인자로 받아 파일이나 I/O 스크림을 걸러주거나 필터링 해줍니다. 이런 예제는 예 A-7 와 예 A-12 를 참고하세요.
Dougherty와 Robbins가 쓴 "Sed & Awk"에서 정규 표현식에 대한 완전하고 명쾌한 사용법을 볼 수 있습니다(서지사항 참고).
주석
[1] |
어떤 메타문자도 포함하지 않아서 문자열 자체의 뜻을 그대로 갖고 있는 문자열이 가장 간단한 형태의 정규 표현식입니다. | |
[2] |
sed, awk, grep은 한 줄에 대해서 처리를 하기 때문에 뉴라인을 처리하지 못 합니다. 뉴라인이 들어 있는 여러 줄에 걸친 표현식에서 점(.)은 뉴라인과 일치합니다.
|
19.2. Globbing
Bash 자체는 정규 표현식을 이해하지 못 합니다. 스크립트에서는 sed 와 awk 같은 명령어나 유틸리티가 정규 표현식을 해석해 줍니다.
Bash는 "globbing"이라고 하는 파일명 확장을 수행해 주는데 이는 표준 정규 표현식을 쓰지 않고, 대신에 와일드 카드를 인식하고 확장해 줍니다. globbing은 표준 와일드 카드 문자인 *, ?, 대괄호속의 문자 목록, 다른 특수 문자들(일치하지 않도록 부정해 주는 ^ 같은 문자)을 해석해 줍니다. 하지만 globbing시, 와일드 카드 문자 사용에는 중요한 몇가지 제한 사항이 있습니다. 예를 들어, *는 .bashrc처럼 점으로 시작하는 파일과 일치하지 않습니다. [1] 비슷하게, ?도 파일명 확장에서 쓰이면 정규 표현식의 일부분으로 쓰일 때와는 다른 의미를 갖습니다.
bash$ ls -l total 2 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh -rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt bash$ ls -l t?.sh -rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh bash$ ls -l [ab]* -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 bash$ ls -l [a-c]* -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 bash$ ls -l [^ab]* -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh -rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt bash$ ls -l {b*,c*,*est*} -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt bash$ echo * a.1 b.1 c.1 t2.sh test1.txt bash$ echo t* t2.sh test1.txt |
echo 명령어도 파일이름에 대해서 와일드 카드 확장을 해 줍니다.
예 10-4를 참고하세요.
주석
[1] |
파일명 확장은 직접적으로 점(dot)을 표시해줘야 도트파일(dotfile)과 일치합니다.
|
'UNIX > 유닉스 공통' 카테고리의 다른 글
[스크랩] 쉘프로그래밍 문법 우왕 (0) | 2014.05.22 |
---|---|
[스크랩] 리눅스 정규식 , 메타문자 (0) | 2014.05.22 |
[스크랩] AWK 명령 자세히 (0) | 2014.05.22 |
[스크랩] AWK 명령어 상세 사용법 (0) | 2014.05.22 |
[스크랩] DNS 검색할 때 어떤 걸 먼저 보게 할건가? /etc/nsswitch.conf (0) | 2014.04.15 |