expr
이 명령은 외부 명령인데요.
bash 의 경우 [[ ]]
특수 명령과 매개변수 확장 기능을 통해
shell 변수를 이용한 regex 매칭, substr 같은 기능을 기본적으로 사용할 수 있습니다.
하지만 sh
의 경우는 그런 기능을 제공하지 않기 때문에 외부 명령을 사용해야 하는데요
이때 사용할수 있는 명령이 expr 입니다.
expr 는 보통 산술연산을 하는 명령으로 알고 있는데 sh
에서 사용할수 있도록
다음과 같은 유용한 기능을 제공합니다.
regex 매칭
매칭에는 Basic Regular Expressions 을 사용하므로 다음과 같은 regex 메타문자를 사용할 때는 escape 해야 합니다.
?
, +
, ( )
, { }
, |
regex 매칭은 다음과 같이 두 가지 형태로 사용할 수 있습니다.
expr STRING : REGEX
expr match STRING REGEX
실행시 기본적으로 매칭 되는 문자 수를 stdout 으로 출력하므로 필요하지 않을 경우 /dev/null 로 redirection 하면 됩니다.
$ AA="foo 12345 bar"
# 기본적으로 매칭 되는 문자 수를 stdout 으로 출력
$ expr "$AA" : "foo [0-9]\+"
9
$ expr "$AA" : "foo [0-9]\+" > /dev/null
$
# if 문에서 다음과 같이 사용할 수 있습니다.
$ if expr "$AA" : "foo [0-9]\+" > /dev/null
then echo Yes
else echo No
fi
Yes
한가지 참고해야 될 사항은 매칭은 앞에서부터 한다는 것입니다.
( ^
anchor 가 기본적으로 사용되는 것과 같습니다. )
그러므로 다음 첫 번째 경우는 참이지만 두 번째는 거짓이 됩니다.
$ expr "$AA" : "foo [0-9]\+"; echo status : $? # 참
9
status : 0
$ expr "$AA" : "[0-9]\+ bar"; echo status : $? # 거짓
0
status : 1
# 따라서 뒷부분을 매칭하려면 다음과 같이 해야 됩니다.
$ expr "$AA" : ".*[0-9]\+ bar"; echo status : $?
13
status : 0
보통 변수와 regex 스트링 앞에 문자 X
를 두어서 많이 작성합니다.
이것은 뒷부분에도 나오지만 $AA 변수값이 expr 명령에서 사용되는 키워드일 경우
오류가 발생하는 것을 방지하기 위한 방법이기도 합니다.
$ if expr "X$AA" : "X.*[0-9]\+ bar" > /dev/null
then echo Yes
else echo No
fi
Yes
\( \)
을 이용해서 매칭 되는 부분만 뽑을 수 있습니다.
$ expr "X$AA" : "Xfoo \([0-9]\+\)"
12345
$ BB=$(expr "X$AA" : "Xfoo \([0-9]\+\)")
$ echo $BB
12345
length
스트링의 length 를 반환합니다.
length STRING
$ AA=1234567890
$ expr length "$AA"
10
index
스트링에서 CHARS 위치를 반환합니다.
index STRING CHARS
$ AA="value=12345"
$ expr index "$AA" "="
6
# 두 개 이상의 CHARS 를 사용할 경우 처음에 매칭 되는 위치가 반환됩니다.
$ AA="foo:bar=123"
$ expr index "$AA" "=:"
4
substr
스트링에서 postion 과 length 를 이용해 특정 부분을 추출합니다.
substr STRING POS LENGTH
$ AA="value=12345"
$ idx=$(expr index "$AA" "=")
$ len=$(expr length "$AA")
$ expr substr "$AA" $(( idx + 1 )) $(( len - idx ))
12345
+
문자의 사용
"match", "length", "index", "substr" 는 expr 명령의 키워드 인데요.
동일한 스트링이 변수 값으로 사용되면 expr 명령이 구분할 수 없으므로 오류가 발생합니다.
이때는 앞에 +
문자를 붙여주어 문제를 해결할 수 있습니다.
# 변수의 값이 expr 명령의 키워드와 동일한 "length"
$ AA=length
$ expr "$AA" : "len[a-z]\{3\}"
expr: syntax error
# 앞에 '+' 붙여 문제 해결
$ expr + "$AA" : "len[a-z]\{3\}"
6
# 또는
$ expr "X$AA" : "Xlen[a-z]\{3\}"
7
# 변수의 값이 expr 명령의 키워드와 동일한 "match"
$ AA=match
$ expr length "$AA"
expr: syntax error
$ expr length + "$AA"
5
# "--" 스트링의 경우
$ AA="--"
$ expr "$AA" : "-[0-9]$\|-$\|--$"; echo status : $?
expr: syntax error
status : 2
$ expr + "$AA" : "-[0-9]$\|-$\|--$"; echo status : $?
2
status : 0
# 또한 '+' 문자를 사용할 때도 앞에 '+' 를 붙여야 한다.
$ AA="foo+bar"
$ expr index "$AA" "+"
expr: syntax error
$ expr index "$AA" + "+"
4
따라서 변수와
+
문자 앞에는 기본적으로+
를 붙여 사용하는 것도 오류를 줄일 수 있는 방법입니다.