본문 바로가기

잡담

Perl에서 newline 매칭하기

어제 새벽에, inureyes님이 갑자기 메신저로 말을 걸으신 게 화근이었다. Tattertools 1.1 Development Alpha 버전을 릴리즈하기 위해서, 간단한 코드 최적화를 하시는 모양이었는데, php 코드에서 쓸모 없는 php 구분 영역 기호 열기/닫기를 없애려고 하시는 거였다.

원래 의도했던 바는
... ?>
<? ...
과  같은 형태를 없애 앞뒤를 한 줄로 이어버리는 것이었다. 당연히, 패턴에는 newline이 포함됐다.
이것을 inureyes님은 find . -name "*.php" -exec perl -pi -e "/\?>\n<\?//" {} \;이라는 쉘 명령어로 하려고 하셨는데 계속 안 되고 있었던 것이다. (위 명령어의 내용을 해석하면, 현재 디렉토리와 그 하위 디렉토리 안의 모든 php 파일들에 대해서 perl을 이용해 저런 패턴 치환을 수행하라는 뜻이다)

newline을 perl 정규표현식에서 표현하는 방법이 잘못됐나 해서 한참 뒤져봤으나 그건 아니었고.. 일단 저 명령어 자체가 맞는지 알아보려고 다른 임의의 패턴을 만들어 써본 결과 저 명령어 자체는 잘 동작하고 있었다.

그래서 왜 그럴까 하고 한참 뒤져보고, #gnome 채널에도 가서 사람들한테 물어보고 그랬는데, 누군가 /s라는 옵션을 붙여보라고 했다. 그게 뭔가 찾아봤더니(man perlre) 전체 입력 문자열을 한 줄인 것처럼 해석하게 하는 것인데, 다른 건 다 똑같고 단지 정규표현식에서 "임의의 한 글자"를 나타내는 .이 newline도 매칭하도록 만드는 역할이었다. (보통 perl로 패턴 치환을 할 때 줄 단위로 하기 때문이다)

근데, 문제는 그래도 안 된다는 거였다.

도대체 왜 그럴까 하면서 삽질 끝에, newline이 패턴의 맨 끝(/pattern/replacement/option 형태로 쓰는데, 두번째 / 앞에 \n이 오는 경우)에 있으면 matching 및 치환이 잘 이루어지는데, 패턴의 중간에 있으면 안 된다는 것을 알 수 있었다.

왜 그럴까? ㅠㅠ Perl의 버그가 아닐까 하는 추측도 해보고 있지만, 이미 수많은 사람들에 의해 오랫동안 사용되어 온 perl에서 이렇게 쉽게 발견될 만한 버그가 있을 것 같지도 않고.. IRC에서는 래리월에게 물어보라는 얘기까지 나왔다.; 결국 원인은 아직 못 찾았고...

고로, 아시는 분은 좀 알려주세요~! -_-;