bash의 printf로 유니 코드 문자열 채우기

Sep 13 2020

나는 bash의 printf로 유니 코드 문자열을 채우려 고 시도했고 그것을 보았습니다.

printf "%2s" a

예상되는 "a"를 산출합니다.

유니 코드 변형

printf "%2s" ä  

놀랍게도 패딩되지 않은 "ä"가 생성됩니다. (zsh는 예상 결과를 제공합니다.)

원인은 무엇입니까? 그리고 bash에서 유니 코드 문자열을 어떻게 채울까요?

답변

crackpot Sep 13 2020 at 00:02

bash에서 유니 코드 문자열을 어떻게 채울까요?

그것은 bash의 기능을 뛰어 넘는 방법입니다. "유니 코드 문자열"을 ascii ++ (이중 너비 문자 없음, bidi 없음, 비 간격 표시 없음 등)로 제한하는 경우 다음과 같이 심사를받을 수 있습니다.

% pad(){ printf '%*s%s\n' "$(($1-${#2}))" "" "$2"; }
% pad 2 €
 €
Quasímodo Sep 13 2020 at 00:06

문자 ä는 UTF-8에서 2 바이트로 인코딩되므로 Printf는 2 바이트를 사용합니다.

Wc는 문자열 의 문자 ( -m)와 바이트 ( -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 äéßôçÈ
    äéßôçÈ
schily Sep 12 2020 at 23:48

bash가 올바르게 작동하고 C 프로그램

#include <stdio.h>
main()
{
        char foo[] = "ä";

        printf("%2s\n", foo);
}

동일하게 작동합니다.

% s는 바이트 지향 문자열을 나타내며 UTF-8의 'ä'는 2 바이트가되기 때문입니다.

내가 테스트 할 수있는 한, 다른 셸은 잘못 작동하지 않습니다.

예상 한 결과는 다음과 같이 볼 수 있습니다.

printf '%2S\n' ä

그러나 이것은 내가 테스트 한 셸에서 지원되지 않습니다.