텍스트 파일에서 한글 글자만 뽑아내기 by Clojure

Language/Clojure 2011. 10. 14. 12:47 Posted by 알 수 없는 사용자
해결하고자 하는 문제는 텍스트 파일에서 한글 글자만 뽑아내는 것이다. 문서에 "한글은 영어로 Korean이라 합니다."라는 내용이 있다면 (한 글 은 영 어 로 이 라 합 니 다) 라고 뽑아내고 싶다는 것. 그리고 글자의 중복이 있으면 제거한다.  위 예제에는 중복이 없다. 코드는 아주 간단하다.
(ns korean-word-extractor.core
  (:gen-class))

(defn -main [& args]
  (let [file-name (first args)
        file-contents (slurp file-name)
        korean-chars (distinct (filter #(<= 0xAC00 (int %) 0xD7AF) (seq file-contents)))] ;; 0xAC00 ~ 0xD7AF: Hangul Range
    (println korean-chars)))
파일명은 argument로 받기로 하고, slurp을 이용해 모든 내용을 일단 얻어온다. 그 다음 한 줄의 코드가 사실 모든 일을 다 하게 되는데, 과정은 다음과 같다.
  • 우선 clojure에서는 문자열에 seq 함수를 적용하면 바로 개별 문자를 list로 활용할 수 있다.
  • 그 다음 한글을 필터링 해야 되는데 filter 함수를 사용할 수 있다. 0xAC00 ~ 0XD7AF는 Unicode의 한글 음절 범위이다. Unicode.org의 Hangul Syllables 문서를 보면 잘 나와있다.
  • 한글 문자만 뽑아내는데 성공했으니 중복된 문자를 제거하면 된다. distinct 함수를 활용하자.
문제가 해결되었다.
한글과 English가 섞여 있을 경우
한글만 extract할 수 있을까?
라는 내용을 담고 있는 test.txt 파일을 만들고 실행해보면,
>lein run test.txt
(한 글 과 가 섞 여 있 을 경 우 만 할 수 까)
와 같이 원하던 결과를 얻게 된다.

Common Lisp는 Unicode를 처리할 수 있을까?

Language/Common LISP 2011. 10. 14. 12:02 Posted by 알 수 없는 사용자
리스프 관련 책을 읽다가 문자열에 대한 이야기가 나왔다. 문득, 리스프가 유니코드를 처리할 수 있을까 하는 의문이 들었다. 그리고 몇 가지 실험을 해보니 전혀 한글을 해석하지 못한다는 것을 알게 되었다.

하지만 분명 설정의 문제이리라.

"SBCL unicode"로 구글링을 해보니 SBCL은 이미 유니코드에 대한 지원을 하고 있다는 것을 알 수 있었다. 컴파일 때 옵션을 줄 수 있고 하는데 나는 우분투에서 패키지로 깔았으니 옵션을 켜고 컴파일 한 것인지 아닌지 알 수가 없다. 그냥 실험을 해보면 알게 되겠지.

모든 정보는 이 곳에서 얻었다. 결론은 간단하다. 우선 emacs가 기본적으로 유니코드(UTF-8)를 사용하게 하고, SLIME도 유니코드를 사용하게 설정하면 된다는 것.

Emacs의 메뉴바에서
Options -> MULE(Multilingual Environment) -> Set Language Environment -> UTF-8을 선택하고,
Options -> Save Options를 선택해서 저장
이렇게 하면 .emacs의 custom-set-variables에 '(current-language-environment "UTF-8")라는 것이 자동 추가된다. 이멕스의 언어 환경을 UTF-8로 바꿔주는 것이다.

다음으로 SLIME을 설정해야 하는데, .emacs에 다음 한 줄만 추가해주면 된다.
(setq slime-net-coding-system 'utf-8-unix)
이멕스를 다시 실행시켜 환경 변수가 적용되게 한 후, SLIME을 띄우자.
CL-USER> #\한
#\UD55C

CL-USER> "한글"
"한글"
오. 한글을 인식한다.
CL-USER> (char-code #\한)
54620
'한'이라는 글자에 대한 코드를 얻어낼 수 있다.
CL-USER> (code-char 54620)
#\UD55C
역으로 글자로 변환. 이렇게 character code를 보면 재미가 없으니 확실히 확인해보자.
CL-USER> (coerce '(#\UD55C) 'string)
"한"
모든 것이 잘 동작한다. 그렇다면 함수 이름으로 활용해보자.
CL-USER> (defun 안녕 ()
       (format t "안녕하세요.~%"))
안녕
CL-USER> (안녕)
안녕하세요.
NIL
완벽하다.

ps. CLISP를 가지고 실험해보니 CLISP에서도 모두 잘 동작한다.