2011년 2월 10일 목요일

이맥스의 정규 표현식 치환 기능

드디어 매스매티카 8을 쓸 수 있게 되었다. 이전 버전에서 작업하던 파일을 열어 실행하니 왠 걸. 떡하니 에러가 뜬다.

매스매티카 8.0의 변경사항으로 인해 발생하는 오류


난 매스매티카를 주로 이론적 분석, 즉 수식전개 등에 사용하는데, 종종 중간 결과를 수식번호 형식으로 저장해 놓는다. 해당 장(chapter)과 각 장에서의 수식번호를 나타내는 eq15\[Dash]8과 같은 형식의 변수명을 사용하는데, 여기서 문제가 발생했다. 이전 버전까지는 eq15-8을 단일 변수명으로 봤는데, 8.0에서는 이를 eq15, \[Dash], 8의 곱으로 인식한다.

어차피 각 장은 별도의 파일에 저장하고 있으므로, 변수명에서 장 번호를 없애기로 했다. 그러면 변수명을 eq8과 같이 \[Dash] 없이 쓸 수 있으므로 문제를 해결할 수 있다. 파일 마다 많게는 100여개에 이르는 수식번호를 어떻게 일일이 다 바꿀까? 매스매티카에서 하기는 어려울 것 같다. 간단한 방법을 생각해보면, sed를 이용할 수도 있고 이맥스의 치환 기능을 이용할 수도 있겠다. 일단 변환할 문자열의 형태를 알아야 하니, 이 파일을 이맥스에서 열어보자.

이 부분의 해석 방식이 바뀌었다.

해당 부분의 입력이 위와 같이 저장된 것을 알 수 있다. 이제 이러한 패턴을 찾아서 바꾸면 된다. replace-regexp(C-M-%) 명령을 이용하면, 정규 표현식으로 위와 같은 패턴의 문자열을 모두 찾아서 바꿀 수 있다. 위 그림에서 강조한 부분을 나타내는 정규 표현식은 아래와 같다.
RowBox\[{"eq15", "\\\[Dash\]", "[0-9][0-9]*"}\]
하지만, 문제가 하나 있다. 패턴은 이게 맞는데 매번 치환마다 수식번호를 그것에 맞게 바꿔줘야 한다. 그렇지 않으면 모든 수식번호가 하나로 바뀌게 된다. 이건 패턴의 변수 기능을 이용하면 해결할 수 있다. 먼저, 수식번호에 해당하는 부분을 괄호로 둘러싼다. Query replace regexp:에 입력할 정규 표현식은 아래와 같다.
RowBox\[{"eq15", "\\\[Dash\]", "\([0-9][0-9]*\)"}\]
괄호로 둘러싼 부분은 치환된 문자열에서 \1로 불러올 수 있다. 괄호가 두 개 이상이면 \2, \3 등으로 불러올 수 있다. 즉, with:에 입력할 패턴은 아래와 같다.
"eq\1"
일치하는 문자열을 한번에 모두 치환하려면 Query replacing이 진행 중일 때, !를 입력하면 된다.

replace-regexp를이용하여 치환하는 모습

문자열 치환을 마치고, 파일을 저장한다. 이제 수정한 파일을 매스매티카에서 열어보자.

노트북 파일을 매스매티카 외부에서 수정하면 저장된 임시 계산 결과를 이용할 수 없다.

경고창이 하나 뜨는며 살짝 겁을 준다. 잘 읽어보면, 수정된 파일이므로 임시 저장 결과를 이용할 수 없다는 안내이다. 친절하게도 내용에는 문제가 없을 거라며 안심 시켜준다. OK를 클릭해서 넘어간다. 수식을 다시 실행해보면, 문제가 해결된 것을 볼 수 있다.

이맥스와 정규 표현식을 이용하면 문제가 되는 부분을 한 번에 모두 치환할 수 있다.