2017년 1월 31일 화요일

특수문자 feff 찾기

텍스트 파일에 특수문자 U+FEFF (Byte Order Mark, BOM)이 포함된 부분을 찾기 위해, grep을 시도했는데 일반적인 방법으로는 잘 매치되지 않는다.

$ cat input.txt | grep -P '\xef\xbb\xbf'

여기저기 찾아보면서 시도해봤는데 위와 같이 하니까 매치된다. vi 에서는 <feff> 이렇게 보이지만, 이 파일은 UTF-8 이라서 실제로는 \xef\xbb\xbf 이렇게 3바이트로 되어있다.

참고: [위키피디아 '바이트 순서 표식']



2017년 1월 16일 월요일

perl에서 계산식을 print할 때 문제


$ perl -e 'print 2**0.5**2'
1.18920711500272

perl 에서 이런 계산식 결과 값을 출력해봤는데 결과가 예상과 다르게 나와서 버그를 발견한 건 아닌가 생각했다. 2의 0.5 승, 즉 sqrt(2)에 다시 2승을 하면 2가 나와야 할 것 같은데 다른 값이 나왔다. perl 버전이 오래된 것이라서 그런가해서 여러 버전의 perl로도 해봤다. 결론부터 말하자면 버그는 아니다. print 사용법과 ** 연산자의 associativity 때문에 발생하는 것이다. +, - 등의 연산자는 left associativity를 가지지만 ** 연산자는 right associativity를 가진다. 그러면 왼쪽 먼저 계산이 되도록 괄호를 쓰면 되는데 그래도 결과가 원하는대로 안나온다. use warnings을 추가해보면 구체적인 이유를 알 수 있다.

$ perl -e 'use warnings; print (2**0.5)**2'
print (...) interpreted as function at -e line 1.
Useless use of exponentiation (**) in void context at -e line 1.
1.4142135623731

print 가 함수로 처리되어서 print(2**0.5) 가 먼저 처리되고 그 결과(void)에 대하여 **2를 하려고 하니 원하는대로 나오지 않는다. warning 메시지가 하나 나오긴 하지만..

$ perl -e 'use warnings; print ((2**0.5)**2)'
print (...) interpreted as function at -e line 1.
2

전체를 감싸는 괄호를 하나 더 추가하니 원하는 결과가 나왔다.

언어 특성상 어쩔 수 없기는 하지만 자칫 실수하기 쉬운 특징인 것 같다. 가능한 print 문 내에 계산식을 쓰지 않고 먼저 계산 값을 변수에 저장해서 그 변수를 출력하도록 하는 것이 좋겠다. 그리고 use warnings를 함께 쓰는 것도 예방하기 좋을 것 같다.(다만 use warnings를 쓰면 실행은 정상적으로 되어도 불필요하게 메시지 출력이 과도해서 출력 메시지를 저장하면 disk full 등의 문제가 발생할 수 있다.)

$ perl -e 'use warnings; $r=(2**0.5)**2; print $r'
2