CLI :: Regular expressions and Metacharacters

Regular expression(정규표현식)
문자열(string, set of characters)의 패턴(pattern)을 기술하는 표현식(expression)
  1. Literal characters
    가장 기본적인 것으로 하나의 문자로 그 패턴을 표현한다.
  2. Character classes(, Character sets)
    지정 가능한 임의의 문자들의 집합이나 특정 범위의 문자들로 부터 오직 하나의 문자를 매치시킨다. [, ]를 사용하며, [   ], [ - ], [^ ]으로 기능이 분류된다.
    (Shorthand 표기법) \d, \D, \w, \W, \s, \S와 같이 간편하게 문자의 집합을 지정할 수도 있다.
  3. Alternation(, Union of expressions, OR operation)
    하위 표현식(subexpression)을 vertical bar(|)로 구분해 나열한다. 표현식의 합집합으로 각각의 표현식들이 교대로 모두 적용된다.
  4. Repetition(, Quantification)
    앞의 표현식이 얼마나 자주 반복될 지를 기술한다. ?, *, +, {, }, *?, +?를 사용하며, {m}, {m, }, { , n}, {m, n}의 형식으로 반복 횟수를 지정할 수 있다.
  5. Anchors
    문자가 아닌 위치(position)을 표현하며, ^, $, \b, \B를 사용한다.
    zero-width patterns이다.
  6. Grouping
    ( )를 사용해 표현식의 블럭(재호출 가능한 Marked subexpression)이나 표현식의 실행단위(Atom) 및 적용의 우선순위를 기술한다.
  7. Backreferences
    \digit(1-9)의 형식으로 이전에 매치된 블럭(Marked subexpression)를 재호출역참조한다. 정의된 블럭의 순서를 통해 재호출 또는 역참조하며, 전체 표현식 내에 마킹 가능한 블럭의 최대 개수는 1~9개이다.

Metacharacter(메타문자)
표현식에서 본래의 문자적(literal) 의미가 아닌 특수한 의미로 사용되는 문자
  1. Basic
    .   *   [   ]   ^   $   \digit   (   )   {   }   [=   =]   [:   :]
  2. Extended
    ?   +   |   (   )   {   }


grep, "search globally for matches to the regular expression, and print lines"
sed, stream editor
.
any single character, 즉 아무(공백 포함, newline 제외) 문자 하나와 매치된다.
[root@haan Working]# cat test.txt
he is a rat
he is in a rut
I like root beer

[root@haan Working]# grep 'r.t' test.txt
he is a rat
he is in a rut

|
구분되어 나열된 각각의 패턴을 모두 매치한다. 적용 우선순위가 가장 낮다는 것에 유의해야 하며, 우선순위를 높이기 위해서는 ( )를 사용한다.
[root@haan Working]# cat test.txt
The pet store sold cats, dogs, and birds.

# 확장 표현식을 위해 grep의 -E 옵션, 또는 egrep를 사용한다.
[root@haan Working]# grep -E 'cat|dog|bird' test.txt
The pet store sold cats, dogs, and birds.

# 우선 순위가 가장 낮고, ()를 사용해 우선순위를 높일 수 있다.
[root@haan Working]# grep -E 'cat|dog.|bird' test.txt
The pet store sold cats, dogs, and birds.
[root@haan Working]# grep -E '(cat|dog).|bird' test.txt
The pet store sold cats, dogs, and birds.

[   ]
only one out of serveral characters, 지정한 문자 집합으로 부터 하나의 문자를 매치한다.
  1.   ]
    [, ]으로 둘러싸인 문자들 중에서 어떤 것이든 하나(any one)와 매치한다.
  2. - ]
    hypen을 이용해 문자의 범위를 지정할 수 있다.
    [0-9]는 0과 9사이의 숫자, [A-Z]는 알파벳 대문자, [a-z]는 알파벳 소문자 하나, [A-Za-z]는 모든 알파벳 중 하나와 매치된다.
  3. [^  ]
    bracket 사이의 첫 위치에 ^(caret)을 사용하면 지정한 문자들을 제외한 문자 중 하나를 매치한다.
    예를 들어, [^24a-z]는 숫자 2, 4와 알파벳 소문자를 제외한 문자들 중 하나와 매치된다.
# grep의 -o 옵션으로 라인을 출력하는 대신 매치되는 부분만을 출력한다.
[root@haan ~]# grep -o 'gr[ae]y'
it matches both gray or grey.
gray
grey

# sed는 패턴 검색 후 새 문자열로 대체한다. 's/패턴/새문자열/g'의 형식이다.
# 벗겨달란다. 기꺼이 HTML 태그를 벗겨내 본다.
[root@haan ~]# sed 's/<[^>]*>//g'
<strong>strip me</strong>
strip me

\d
numeric character, [0-9_]와 같은 의미이다.
\D
non-numeric character, [^0-9_] 또는 [^\d]와 같은 의미이다.
\w
word character, 일반적으로 [A-Za-z0-9_]와 같은 의미이다.
\W
non-word character, 일반적으로 [^A-Za-z0-9_] 또는 [^\w]와 같은 의미이다.
\s
whitespace character, [ \t]와 같은 의미이다.
\S
non-whitespace character, [^ \t] 또는 [^\s]와 같은 의미이다.
# 위의 표기법은 grep, sed에서 지원하지 않는다. python을 사용하자.
# [\S\D]와 [^\s\d]는 다르다는 것에 유의하자.
[root@haan Working]# python
>>> import re
>>> text = "x 8"
>>> print re.sub("[\S\D]", "r", text)
rrr
>>> print re.sub("[^\s\d]", "r", text)
r 8
>>> Ctrl-D

^
Multi-line mode에서 라인의 시작 위치와 매치된다.
$
Multi-line mode에서 라인의 끝 위치와 매치된다.
\b
(word boundary) matches before and after an alphanumeric sequence, non-word charater(\W)로 둘러싸인 word character(\w)의 전/후 위치가 매치된다.
\B is the negated version of \b.
[root@haan Working]# cat test.txt
line, at the first
This is the second line

# 실행 후 실제 출력 부분은 노란색으로 구분하였다.
[root@haan Working]# grep '^line' test.txt
line, at the first
[root@haan Working]# grep 'line$' test.txt
This is the second line

# "c"로 시작해서 "t"로 끝나는 단어("cat")를 추출해 보자.
[root@haan ~]# grep -o '\bc.*t\b'
um... can you match cat only?
can you match cat
# 헤헤... 예상대로 실패다.

# 스페이스를 제외([^ ])하고 다시 한다.
[root@haan ~]# grep -o '\bc[^ ]*t\b'
um... can you match cat only?
cat
# 성공이다!!

?
바로 전의 표현식(block)을 0, 1번의 횟수만큼 반복한다.
[root@haan ~]# grep -E -o 'colou?r'
how spell the word, "color" or "colour"?
color
colour

# 메타문자를 원래의 literal 의미로 쓰고자 할 때는 백슬래시()로 escape시킨다.
# 확장 표현식을 위해 sed의 -r 옵션을 사용한다.
[root@haan ~]# sed -r s/'Jan.?(uary)?'/01/g
Jan or Jan. or January
01 or 01 or 01
10-Jan-2005, 20-Jan.-2005, 30-January-2005
10-01-2005, 20-01-2005, 30-01-2005

*
바로 전의 표현식(block)을 0, 1 or any number 횟수만큼 반복한다.
+
바로 전의 표현식(block)을 at least(>=) 1, 즉 최소한 한번 이상 반복한다.
[root@haan ~]# grep -o 'go*gle'
how often? zero time, ggle
ggle
how often? one time, gogle
gogle
how often? more times, gooooooogle
gooooooogle

# 위와는 달리 "ggle"은 매치되지 않음을 알 수 있다.
[root@haan ~]# grep -E -o 'go+gle'
how often? zero time, ggle
how often? one time, gogle
gogle
how often? more times, gooooooogle
gooooooogle

Lazy(Non-greedy) quantifiers
반복연산자 *, +는 기본적으로 breedy해서 가능한 최대로 매치하는데, 매치를 최소로 제한하기 위해서 Lazy quatifiers(*?, +?)를 사용한다.
# Greedy, as much as possible
[root@haan Working]# grep -P -o 'L.*s '
Lazy quantifier grab as little as possible.
Lazy quantifier grab as little as

# Lazy, as little as possible
[root@haan Working]# grep -P -o 'L.*?s '
Lazy quantifier grab as little as possible.
Lazy quantifier grab as

{   }
바로 전의 표현식(block)의 반복 횟수를 지정한다. m(min)~n(max)
  1. {m}
    정확히 m만큼 반복한다.
  2. {m, }
    m~∞만큼 반복한다. 따라서, {0, }은 *와 {1, }은 +와 같은 의미이다.
  3. { , n}
    0~n만큼 반복한다. 따라서, {, 1}은 ?와 같은 의미이다.
  4. {m, n}
    m~n 만큼 반복한다.
[root@haan Working]# cat test.txt
aaaaa bbbbb ccccc
aaa bbb ccc
aaaaa bbbbbbbbbbbbbb ccccc

# grep가 { ,n}을 지원하지 않아서 {0, n}을 대신 사용한다.
# 실제로 출력되는 부분은 노란색으로 구분하였다.
[root@haan Working]# grep -E -o 'a{5} b{0,6} c{3,4}' test.txt
aaaaa bbbbb ccccc
aaa bbb ccc
aaaaa bbbbbbbbbbbbbb ccccc

[root@haan Working]# grep -E -o 'a+ b{4,} c?' test.txt
aaaaa bbbbb ccccc
aaa bbb ccc

aaaaa bbbbbbbbbbbbbb ccccc
[root@haan Working]# grep -E -o 'a{5} b{6,} c{4,8}' test.txt
aaaaa bbbbb ccccc
aaa bbb ccc

aaaaa bbbbbbbbbbbbbb ccccc

(   )
표현식의 실행단위(Atom) 및 적용의 우선순위를 지정하기 위한 Grouping에 사용되며, 동시에 Backreference(역참조 or 재호출)을 위한 Marked subexpression을 정의한다.
[root@haan Working]# cat test.txt
Billy tried really hard.
Sally tried really really hard.
Timmy tried really really really hard.

# "really "가 1번 이상 반복되는 문자열을 "very " 문자열로 바꿔보자.
# 'really ' 표현식을 ()로 grouping한 후 1번 이상(+) 반복 매치한다.
[root@haan Working]# sed -r 's/(really )+/very /g' test.txt
Billy tried very hard.
Sally tried very hard.
Timmy tried very hard.

[root@haan Working]# cat test.txt
abc xyz
xyz abc
abc abc
xyz xyz

# '(abc|xyz)' marked block을 정의하고 '\1'을 통해 그 것을 재호출한다.
[root@haan Working]# egrep '(abc|xyz) \1' test.txt
abc xyz
xyz abc

abc abc
xyz xyz

# 다음 예제를 보면 단순 반복과 재호출의 차이점을 알 수 있다.
[root@haan Working]# egrep '(abc|xyz) (abc|xyz)' test.txt
abc xyz
xyz abc
abc abc
xyz xyz


\digit(1-9)
이전에 매치된 블럭(marked subexpression)을 순서(1~9)를 통해 역참조(해당 블럭에 매치된 결과값 가져오기) 및 재호출한다.
[root@haan Working]# cat test.txt
foo(x+13,y-2);
foo(bar(8),x+y+z);

# 매개변수가 2개인 함수의 매개변수들의 위치를 서로 바꿔보자.
[root@haan Working]# sed -r
> 's/([A-Za-z0-9_]+)(([^,]*),([^,]*))/\1(\3,\2)/g'
> test.txt
foo(y-2,x+13);
foo(x+y+z,bar(8));

# 아래 예제도 잘 살표보자.
[root@haan Working]# sed -r 's/([A-Z])([0-9]{2,4}) /\2:\1 /g'
A37 B4 C107 D54112 E1103 XXX
37:A B4 107:C D54112 1103:E XXX

# '(?:pattern)'과 같이 하면 marking하지 않고 grouping이 가능하다.
# grep와 sed 등은 지원하지 않는 표기법이다.
[root@haan Working]# python
>>> import re
>>> text = "A-xyz-37 # B:abcd:142 # C-wxy-66 # D-qrs-93"
>>> print re.sub("([A-Z])(?:-[a-z]{3}-)([0-9]*)", "\1\2", text)
A37 # B:abcd:142 # C66 # D93
>>> Ctrl-D

Lookahead assertions
(?=pattern) for positive assertions, and (?!pattern) for negative assertions.
They are not backreferenced and not marked, likewise (?:pattern).
[root@haan Working]# python
>>> import re
>>> text = "A-xyz37 # B-ab6142 # C-Wxy66 # D-qrs93"
>>> print re.sub("([A-Z])-(?=[a-z]{3})([^\s#]*)", "\2-\1", text)
xyz37-A # B-ab6142 # C-Wxy66 # qrs93-D
>>> print re.sub("([A-Z])-(?![a-z]{3})([^\s#]*)", "\2-\1", text)
A-xyz37 # ab6142-B # Wxy66-C # D-qrs93
>>> Ctrl-D

[root@haan ~]# python
>>> import re
>>> txt = "Iraq is a country, but not Eraq"
>>> print re.sub("([^ ]*)q[^u]", "\1k", txt)
Irakis a country, but not Eraq
>>> print re.sub("([^ ]*)q(?!u)", "\1k", txt)
Irak is a country, but not Erak
>>> Ctrl-D

  1. Basic and Extended Specifications Issue 6
  2. Regular-Expressions.info - Tutorial, Examples and Reference
  3. A Tao of Regular Expressions
  4. Regular expressions with Perl examples by Wikipedia
  5. Regexp Syntax Summary
  6. Learning to Use Regular Expressions

by 달소년 | 2005/11/04 10:11 | 리눅스 | 트랙백 | 덧글(0)

트랙백 주소 : http://lunarboy.egloos.com/tb/843582
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

◀ 이전 페이지          다음 페이지 ▶