나는 bash의 printf로 유니코드 문자열을 채우려고 시도했고 이것을 보았습니다.
printf "%2s" a
예상되는 "a"를 생성합니다.
유니코드 변형
printf "%2s" ä
놀랍도록 채워지지 않은 "ä"를 생성합니다. (zsh는 예상된 결과를 제공합니다.)
이 문제의 원인은 무엇입니까? bash에서 유니코드 문자열을 어떻게 채우나요?
답변1
문자는 ä
2바이트를 사용하여 UTF-8로 인코딩되므로 Printf는 이를 2 패딩으로 처리합니다.
-m
Wc는 문자열의 문자( )와 바이트( )를 계산할 수 있습니다 . -c
그러면 Printf에 주어진 숫자는 입니다 [intended pad]+[bytes]-[chars]
. 그래서 저는 이 pad.sh
스크립트를 조립했습니다.
#!/bin/sh
bytes=$(printf '%s' "$2" | wc -c)
chars=$(printf '%s' "$2" | wc -m)
n=$(($1+bytes-chars))
printf "%${n}s" "$2"
아래 예제 실행에서는 명확성을 위해 각 출력 뒤에 인위적으로 개행 문자를 추가했습니다.
$ sh pad.sh 10 abcdef
abcdef
$ sh pad.sh 10 äéßôçÈ
äéßôçÈ
답변2
Bash에서 유니코드 문자열을 어떻게 채우나요?
이는 bash의 기능을 훨씬 뛰어넘는 것입니다. "유니코드 문자열"을 ascii++로 제한하는 경우(2바이트 문자 없음, bidi 없음, 공백이 아닌 마커 없음 등) 일시적으로 다음과 같이 구성할 수 있습니다.
% pad(){ printf '%*s%s\n' "$(($1-${#2}))" "" "$2"; }
% pad 2 €
€
답변3
bash는 올바르게 작동하고 C 프로그램은
#include <stdio.h>
main()
{
char foo[] = "ä";
printf("%2s\n", foo);
}
행동은 동일합니다.
이는 %s가 바이트 지향 문자열을 참조하고 UTF-8의 "ä"가 2바이트가 되기 때문입니다.
내가 테스트한 한 다른 쉘은 잘못 작동하지 않았습니다.
원하는 결과는 다음을 통해 확인할 수 있습니다.
printf '%2S\n' ä
그러나 제가 테스트한 쉘 중 어느 것도 이를 지원하지 않습니다.