Regex
regex 매칭은 ~
연산자를 사용합니다.
awk 에서 regex 를 작성하는 방법은 regex 상수 (/.../
) 을 이용하는 방법과
스트링을 이용하는 방법 두 가지가 있습니다.
기본적으로 extended regular expression 을 사용하므로
regex 에서 사용하는 ?
, +
, ( )
, { }
, |
문자들을 escape 할 필요가 없습니다.
regex 상수 /.../
를 이용하는 방법
~
연산자를 사용하지 않고 단독으로 사용할 수 있는데 그럴 경우 기본적으로$0
과 매칭합니다.식 내에서 기본적으로 escape 문자가 처리됩니다.
/
or\
문자를 식에 사용하려면 escape 합니다.regex 상수 라고도 하고 변수를 사용하지 못하는 단점이 있습니다.
# /.../ 에서 '\t' escape 문자가 처리되어 매칭이 된다.
$ echo -e '111\t222:333\t444' | awk -F: '$1 ~ /11\t22/ { print $1 }'
111 222
$ echo '/' | awk '///{ print }' # ERROR
$ echo '/' | awk '/\//{ print }' # OK
/
$ echo '\' | awk '/\/{ print }' # ERROR
$ echo '\' | awk '/\\/{ print }' # OK
\
$ echo '\' | awk '/[\]/{ print }' # ERROR
$ echo '\' | awk '/[\\]/{ print }' # OK
\
# '~' 연산자를 사용하지 않고 독립적으로 사용하면 기본적으로 '$0' 와 매칭을 합니다.
# 따라서 다음 예는 awk '$0 ~ /^foobar$/ ...' 와 동일합니다.
$ echo 'foobar' | awk '/^foobar$/ { print }'
foobar
$ echo 'foobar' | awk '{ if ( /^foobar$/ ) print }'
foobar
# 다음 두 식은 결과적으로 동일합니다.
# 매칭이 성공하여 값 1 이 AA 변수에 대입됩니다.
$ echo 'foobar' | awk '{ AA = /^foobar$/; print AA }'
1
$ echo 'foobar' | awk '{ AA = ( $0 ~ /^foobar$/ ); print AA }'
1
# 매칭이 실패할 경우는 0 이 대입됨
$ echo 'foobar' | awk '{ AA = /^fooxxx$/; print AA }'
0
스트링을 이용하는 방법
스트링을 이용하면 regex 식 내에 변수를 사용할 수 있고 또한 regex 식 자체를 변수에 대입해 사용할 수도 있습니다.
단독으로 사용할 수 없고 항상
~
연산자와 함께 사용해야 합니다.스트링을 이용하는 방법의 단점은 regex 상수에 비해 escape 처리가 복잡하다는 점입니다.
# 스트링을 이용하면 식 내에서 변수를 사용할 수 있습니다.
$ echo 'foobar' | awk '{ var = "ob"; if ( $0 ~ "^fo" var "ar$" ) print }'
foobar
# regex 식 자체를 변수에 넣어 사용할 수도 있습니다.
$ echo 'foobar' | awk '{ regex = "^foobar$"; if ( $0 ~ regex ) print }'
foobar
다음은 식을 작성할 때 regex 상수와 스트링의 차이점을 보여줍니다.
스트링으로 작성할 때는 /.../
안에 들어가는 스트링과 동일하게 되도록 만들어준다고 생각하면 됩니다.
# regex 상수로 작성한 경우
$ echo '"111\222":"333\444"' | awk -F: '$1 ~ /"111\\222"/ { print $1 }'
"111\222"
# 동일한 식을 스트링으로 만들 경우
# 먼저 double quotes 은 " " 내에서 escape 해야 하므로 \" 로 작성하고
# '\\' 를 만들려면 '\' 문자는 escape 해야 하므로 '\\\\' 로 작성해야 합니다.
$ echo '"111\222":"333\444"' | awk -F: '$1 ~ "\"111\\\\222\"" { print $1 }'
"111\222"
Regular expression Extensions
sed 에서는 word boundary 와 관련해서 \b
, \B
를 사용하는데 awk 에서는 \y
, \B
를 사용합니다.
(\b
는 backspace escape 문자로 사용됩니다.)
소문자와 대문자가 같이 있는데 대문자는 소문자의 logical NOT 이라고 생각하면 됩니다.
\s
, \S
\s
는 [[:space:]]
를 \S
는 [^[:space:]]
를 나타냅니다.
\w
, \W
\w
는 [[:alnum:]_]
를 나타냅니다. 즉 [:alnum:]
클래스에 _
가 추가된 것입니다.
(-
는 포함되지 않습니다.)
\W
는 [^[:alnum:]_]
를 나타냅니다.
\y
, \B
word boundary 를 나타냅니다.
# \y 의 경우
$ echo 'abc %-= _def.' | awk '{ gsub(/\y/,"X") }1'
XabcX %-= X_defX.
# \B 의 경우
$ echo 'abc %-= _def.' | awk '{ gsub(/\B/,"X") }1'
aXbXc X%X-X=X _XdXeXf.X
-------------------------------------------------
$ echo '*foo_bar' | awk '/\y[a-z]\w+/'
*foo_bar
$ echo '_foo_bar' | awk '/\y[a-z]\w+/'
$
\<
, \>
\<
는 word boundary 인데 word 의 시작 부분을, \>
는 word 의 끝부분을 나타냅니다.
# '\<' 의 경우
$ echo 'abc %-= def.' | awk '{ gsub(/\</,"X") }1'
Xabc %-= Xdef.
# '\>' 의 경우
$ echo 'abc %-= def.' | awk '{ gsub(/\>/,"X") }1'
abcX %-= defX.
대, 소문자 구분 없이 매칭하기
regex 매칭은 기본적으로 대, 소문자를 구분하는데요 구분 없이 매칭을 하려면 다음과 같은 방법을 사용할 수 있습니다.
[ ]
을 이용하는 방법
# Foo, foo 모두 매칭이 된다.
$1 ~ /[Ff]oo/ { ... }
- tolower 함수를 이용하는 방법
tolower($1) ~ /foo/ { ... }
IGNORECASE
builtin 변수를 사용하는 방법
기본값은 0
인데 1
로 설정을 하게 되면 매칭시 대, 소문자 구분을 하지 않습니다.
이 방법을 사용할 때 주의할 점은 변수값 설정은 특정 블록에만 적용되는 것이 아니라
설정된 시점부터 awk 명령이 종료될 때까지 소스코드 전체에 적용된다는 점입니다.
x = "aB"
if (x ~ /ab/) ... # 기본 설정은 대, 소문자를 구분하므로 fail!
IGNORECASE = 1
if (x ~ /ab/) ... # succeed!