bash 터미널 너비 계산하기 문제

eungkyu의 이미지

http://kldp.org/node/84184
위의 post의 답변이라고 볼 수도 있으나, 좀 더 많은 분이 봤으면 하는 생각에 새 글로 올립니다.

예전부터 bash에서 문제가 되던 것이 있었는데, 아직도 안고쳐졌네요. 문제의 원인은 알고 있는데, 아직 고쳐지지는 않았습니다.

보면 bash에서 글자들이 차지하는 너비를 잴 때 글자수로 하고 있습니다.
예를 들어서,

가나다abc

이건 여섯자입니다.

그런데 이것이 실제로 터미널에서 차지하는 영역의 크기는 아홉 칸입니다. 한글 하나가 터미널에서 두 칸을 차지하기 때문이죠. 현재 많은 프로그램이 이 처리를 잘 못하고 있습니다.

bash가 그렇고 ls를 했을때 정렬하는 것도 한글 이름의 파일이 있으면 삐뚤해지는 것을 볼 수 있습니다.

좀 더 자세히... bash에 한정해서 얘기해보겠습니다.

버그의 본질을 얘기하자면, 스트링에서 글자의 수를 재는 것과 터미널에서 차지하는 크기를 잴 때 차이를 두어야 하는데, 그렇게 하고 있지 않기 때문입니다.

bash 2.x 이하에서는 스트링에서 글자의 수를 잴 때 strlen() 류의 함수를 사용했습니다. 그렇지만 strlen() 은 단순히 바이트 수를 재는 것이기 때문에 글자 수를 정확히 재지는 못합니다. 예를들어 "가나다abc"는 여섯자이지만, strlen()으로 재면 9가 나오겠죠. (EUC-KR 환경에서 한글 한 자가 두 바이트를 차지하기 때문)

bash 3.x에서는 국제화를 적용하면서 wide character를 사용하도록 바뀌었습니다. 여기에서는 wcslen()류의 함수를 이용합니다. 이 함수는 strlen()과 다르게 글자의 수를 정확히 잽니다. L"가나다abc"를 인자로 넣으면 6이 나옵니다.

문제는 터미널 너비를 계산할 때 글자의 수를 그대로 이용한다는 것입니다.

bash 2.x 이하에서는 우연하게도 strlen()이 터미널 너비를 정확히 계산해 내었습니다. 한글 한 자가 터미널 두 칸을 차지하는 것과 한글 한 자가 두 바이트를 차지하는 것이 맞아떨어진 것이죠. (물론 한글 뿐만 아니고 일본어나 한자에서도 그렇습니다.)

그래서 비록 글자 수를 정확히 재지는 못하지만, 터미널에서의 문제는 없었습니다.

그런데 bash 3.x로 넘어가면서 터미널 너비를 계산할 때 글자의 수를 그냥 사용함으로서 문제가 발생하게 된 것입니다. "가나다abc"가 터미널에서 차지하는 수는? 하면 9 컬럼이 되어야 하는데 6으로 계산하고 있어서 문제가 발생하는 것입니다. (참고로 바이트 수는 전혀 딴 값입니다. 더이상 EUC-KR만 사용하는 것이 아니기 때문에)

해결책은. wcwidth()와 wcswidth()입니다. 이 함수는 각각 wide character, wide string이 터미널에서 차지하는 컬럼의 크기를 리턴해 주는 함수입니다. 터미널에서 차지하는 컬럼의 크기를 잴 때에는 wcslen() 대신에 위의 함수를 사용해야 합니다.

예전에 한참 bash에서 이것저것 많이 하고 불편을 겪고 시간도 많을 때 한 번 고쳐볼까 하고 본 일이 있는데, 요즘은 여건이 되질 않아서 건드리지 못하고 있습니다.

버그 리포트를 올려봤는지는 잘 기억이 나질 않네요. 버그 리포트를 올려볼까 하다가도 지금까지 말한 것을 영어로 설명하기가 빡쎄서 그만두곤 했었는데, 결국엔 올렸는지 기억이 안나네요 =_=;;

누구 한 번 뛰어들어보세요~

전 요즘 여건상, 리눅스에서 일을 하는 것도 아니고, 현재는 크게 불편을 느끼지 못하는 터라 뛰어들기가 쉽지 않네요.

제가 설명은 다 했으니, 소스코드 헤집으면서 고치기만 하면 됩니다 :)
(bash 소스가 복잡해서 고치기만 하는 것도 쉽지는 않습니다만...)

jg의 이미지

구체적으로 어떠한 경우인가요..
저같은 경우 제현할 수가 없네요. ls 를 통해서도 정렬이 잘되는 것 같거든요.

max=`cat /usr/share/libhangul/hanja/hanja.txt | wc -l`
eval sed -n \'`for ((i = 0; i < 50; ++i));do echo $(($RANDOM%$max +1)); done | sort -n | sed 's|$| s/\\\\([^:]*\\\\):.*/\\\\1/p;|'`\' /usr/share/libhangul/hanja/hanja.txt | xargs touch

댓글 첨부 파일: 
첨부파일 크기
Image icon listtest.png25.41 KB

$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}

eungkyu의 이미지

ls는 그 문제를 해결했을지도 모르겠습니다.
http://kldp.org/node/84184
요기에 bash에서의 문제점이 나오네요.

제가 지금 리눅스를 쓰고 있지 않고 있어서 보여드릴 수가 없네요.
오늘 저녁쯤이나 집에 가게 되면 직접 재현해드리겠습니다.

only2sea의 이미지

그게 CJK Character를 Wide로 처리하느냐 아니냐의 문제이기도 합니다.
보니까 어떤 곳에서는 고정폭에서 Wide를 생각 안 해서 CJK 문자들은 반 너비 정도만 출력되고 짤리는 경우도 있더라구요.

아마록에서 가사와 앨범 표지를... http://kldp.net/projects/amarok-script/

블로그: http://turtleforward.blogspot.com

keedi의 이미지

흠... bash의 문제가 아니지 않을까요?
오히려 터미널과 폰트 사이의 문제이지 않을까요.
영문폰트와 한글폰트의 매칭으로 인한 불일치 문제등...
사실 한글 한글자가 영문 폰트 두 글자와 꼭 맞을 수는 없는것이니...

버그질라에도 비슷한 문제가 있었는데...
버그질라에 글을 등록하면 글을 화면에 보여주기 위해서 래핑할때
글자의 바이트 수로 80바이트(또는 사용자 설정) 단위 등으로 래핑합니다.
하지만 이것은 한글이 한 글자가 2바이트 이고 AND 한글 한 글자가
영어 두 글자 정도의 간격 차지한다는 가정에서만 이쁘게 보이죠.
utf-8 환경에서는 영문이 80글자가 보일때 한글은 겨우 80/3 글자만 보일 뿐이죠.
그런데 이 글자가 차지하는 폭은 대충 80/3*2 (사실 2도 아니죠..)이더군요...

utf-8의 한글이 3바이트고 웹브라우져에서 보는 Sans체로
(은글꼴 + 비트스트림 베르나다)볼 때 이미 한글 한 글자의 간격은
영문 두 글자의 간격보다 좁다는 것이죠...

저는 bash 3.2.13, gnome-terminal,
은글꼴 + 비트스트림 베르나다, ko_KR.UTF-8
를 사용하지만 말씀하신 문제가 발생하지는 않네요.

한참 예전에 gnome-terminal을 사용할 때 말씀하신 비슷한 문제를
겪은 기억은 납니다. 그런데 그게 gnome-terminal 문제인지...
아니면 굴림체와 같은 폰트 문제였는지...또는 말씀하신 것처럼
bash의 문제인지는 정확하게 기억나지 않네요. :-)

---------------------------
Smashing Watermelons~!!
Whatever Nevermind~!!

Kim Do-Hyoung Keedi

----
use perl;

Keedi Kim

dalgarak의 이미지

저쪽 링크에도 이미 적었기 때문에 중복포스팅의 느낌이 나긴하지만, 일단 시작한김에 대충 적어볼까 합니다.

개인적인 생각으로는, wcslen()의 문제가 그리 여러 프로그램에 '지금도' 잔존하는지 잘 모르겠습니다. 물론 흔하게 발생하는 문제이기도 합니다만, 생각보다 수정도 잘 되었던걸로 기억합니다.

위에서 언급한 문제는 PS1, 즉 '프롬프트'에 멀티바이트문자가 들어갈 때'만' 발생합니다. 비단 CJK 사용자만의 문제가 아닙니다. 그것이 디렉토리명이건, date/time 이건 뭐건 PS1 안에 들어가면서 문제가 발생합니다. 게다가 이 문제는 이미 bash 3.2 patchlevel 16에서 해결되었습니다. invisiable character 때문에 커서 이동이 부적절하게 이루어지는 것도 patchlevel 17로 반영되었습니다.

http://ftp.gnu.org/gnu/bash/bash-3.2-patches/bash32-016

http://ftp.gnu.org/gnu/bash/bash-3.2-patches/bash32-017

업스트림에서 해결되었는데 배포판 패키징에 반영이 안되었을 뿐입니다. 현재 최신 버전의 bash에서 별다른 터미널 폭문제를 경험하지 못했습니다.

[굴림,돋움,궁서]'체' 에서 비롯할 법한 글자간 폭문제(globaladvance 였나요? 기억이..) 역시 fontconfig 설정으로 틀어박힌지 오래입니다. 지금은 기본이라고 생각하긴 합니다만.

음, 뭔가 글이 공격적인 느낌이 나는군요. 뭔가를 표현하는데 서툴러서 큰일입니다. 양해 부탁드립니다.
------
http://lunapapa.egloos.com , me2day : lunapapa , IRC: LunA_J`etch@#gnome

jg의 이미지

아, 이 문제가 맞는 것 같습니다. 제 경우 PS1에 색깔을 넣는 걸 호스트명에만
넣는 것으로 제한하는 경우가 많아서 그런문제를 보지 못한 것이군요.
사실 이 글을 쓰기 전에 저도 뭔가 찜찜해서 젠투의 기본 PS1으로도 실험해 보았습니다.
그런데 이것마저도 젠투를 최근에 설치해서 그런지 문제가 발생하지 않았습니다.

$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}

dalgarak의 이미지

http://etchi.cafe24.com/etchi/wiki.php/LunA/2006-11#05
(주소가 바뀌면서 이미지 주소 갱신하느라 저 페이지를 임의로 고치긴 했습니다만.)

그때는 결국 3.2버전 전체를 마스킹해놓고 있었지요. (능력도 부족하고 귀찮음도 심해서 고칠 생각은 엄두도 안내고 있었습니다.) 게다가 x86 에서는 3.1-p1x 가 가장 최신이었기 때문에, ~x86을 사용하던 사람만 경험하던 문제였습니다. 레포팅을 할려다가 영어때문에 순간좌절(....) 하고 버그질라를 뒤지던 중에, 같은 문제를 언급한 레포팅이 올라온것을 확인했습니다.
http://bugs.gentoo.org/show_bug.cgi?id=154062

문제 해결은 여기서 됐습니다. #154062는 중복처리되었지만, 문제를 정확하게 언급한건 #154062 였지요.
http://bugs.gentoo.org/show_bug.cgi?id=155369

패치가 만들어진건 예전이지만, 업스트림에 반영이 계속 안되고 있었습니다. 덕분에 3.2-p10-r1 에 먼저 반영이 되었고, 계속 버전업 하면서 저 패치가 계속 붙어왔습니다. 3.2-p15-r1 이 x86 stable로 올라오게 되면서 이전 버전의 ebuild는 정리되고 남은게 지금 x86, 즉 3.2-p15-r1 입니다. ~x86인 저는 p17을 사용하고 있구요.

app-shells/bash 의 ChangeLog를 인용합니다.

  03 May 2007; Raúl Porcel <armin76@gentoo.org> bash-3.2_p15-r1.ebuild:
  ia64 + x86 stable wrt bug 176882
.. (중략) ...
*bash-3.2_p15-r1 (24 Mar 2007)
 
  24 Mar 2007; Mike Frysinger <vapier@gentoo.org>
  +files/bash-3.2-redisplay-cursor.patch, +bash-3.2_p15-r1.ebuild:
  Add fix for redisplay bug in unicode locales #155369.

------
http://lunapapa.egloos.com , me2day : lunapapa , IRC: LunA_J`etch@#gnome

eungkyu의 이미지

제가 성급했던거 같네요. 예전에 PS1에 한글을 넣다가 발견한 버그였는데 고쳐졌나봅니다 =_=;;
일을 늦게까지 집에가서 오래 보지는 못하고 잠깐 살펴봤는데, 예전에 분명히 보였던 버그가 보이질 않네요 ㅋㅋ

scp에서 비슷한 문제가 보였습니다.

한글 파일과 영어 파일이 섞여있는데서

scp files destination
이렇게 복사하면 한글 글자 하나마다 한칸씩 앞으로 땡겨지는 것을 볼 수 있습니다.

어쨋든 고쳐진 버그가지고 길게 썼더니 약간 뻘쭘하네요 =_=;;