이 스크립트를 사용할 때 "print_unicode: line 9: printf: \u Unicode 0187에 대한 유니코드 번호 누락" 오류가 발생하는 이유는 무엇입니까?

이 스크립트를 사용할 때 "print_unicode: line 9: printf: \u Unicode 0187에 대한 유니코드 번호 누락" 오류가 발생하는 이유는 무엇입니까?

내 터미널에서 유니코드 문자가 어떻게 보이는지 확인하기 위해 이를 쉘 스크립트로 작성했습니다.

#!/bin/bash

X=0

while [ $X -lt 65536 ]; do
    HEX=`bc <<< "obase=16; $X"`
    HEX="0x${HEX}"
    UCODENAME=`printf "%0*x\n" 4 $HEX`
    UCODECHAR=`printf "\u%0*x\n" 4 $HEX`
    echo -e "Unicode ${UCODENAME} = ${UCODECHAR}"
    X=$((X + 1))
done

스크립트를 실행하면 다음과 같은 출력이 나타납니다.

print_unicode: line 9: printf: missing unicode digit for \u
Unicode 0188 = ƈ

두 번째 줄이 바로 내가 찾고 있는 내용입니다.

printf나는 오류를 없애기 위해 이 방법을 엄격하게 사용하려고 노력합니다 .

#!/bin/bash

X=0

while [ $X -lt 65536 ]; do
    HEX=`bc <<< "obase=16; $X"`
    HEX="0x${HEX}"
    printf 'Unicode %0*x = \u%0*x\n' 4 $HEX 4 $HEX
    X=$((X + 1))
done

다음과 같은 결과가 나타납니다.

print_unicode: line 8: printf: missing unicode digit for \u
Unicode 037f = \u037f

두 번째 줄은 내가 찾고 있는 내용이 아니며 여전히 동일한 오류 메시지가 나타납니다.

이 오류를 어떻게 해결할 수 있나요?

보너스: 이에 대한 더 우아한 해결책은 무엇입니까?

답변1

오류가 발생하는 이유는 다음과 같습니다.
내장 printf는 뒤에 실제 숫자 \U(또는)가 올 경우에만 오류를 이해합니다.\u

$ printf '\U0021'
!

숫자를 생성하고 변환하려면 2단계 printf가 필요합니다(큰따옴표를 전달하려면 큰 \가 필요함).

$ printf '%b' "$(printf '\\U%04X' 33)"
!

당신이 원하는 대로:

$ printf '%b' "$(printf '\\u%0*X' 4 33)"
!

이것은 또한 작동합니다:

$ printf '%b' "$(printf '\\U%0*X' 8 33)"
!

bash에게 16진수를 알려주기 위해 bc를 사용할 필요가 없습니다.
bash는 이것을 잘 이해합니다:

$ a=$(( 0xdef )); echo $(( a + 1 ))
3568

숫자의 16진수 값을 얻는 것으로 printf충분합니다 .

$ printf '0x%06x' 3568
0x000df0

이 루프는 다음과 같이 단순화될 수 있습니다.

#!/bin/bash

cp=$((0x020))     len=6

for (( cp=32; cp<$((0x010000)); cp++)); do    
    Ucode="$(printf '%b' "$(printf '\\U%0*X' "$len" "$cp")")"
    printf 'Unicode U%0*x = %s\n' 4 "$cp" "$Ucode"
done

경계하다0x20부터 0x010000(~64k 라인)까지 많은 라인이 있습니다.

UNICODE의 코드 포인트는 최대 10FFFF이므로 len을 6으로 늘렸습니다.

물론 Ucode의 완전한 정의는 다음과 같습니다.

Ucode="$(printf '%b' "$(printf '\\U%0*X' $len "$cp")")"

cpdec=32 또는 HEX=0x20 아래의 코드 포인트( )는 제어 문자입니다.

코드가 이와 같은 코드 포인트에 대해 작동하더라도 나는 그렇게 합니다.아니요그들과 함께 플레이하는 것이 좋습니다.

와는 별개로UNICODE U0000의 경우 값이 변수에 할당되기 때문입니다.

이 인쇄\0

$ printf '%b' "$(printf '\\U%0*X' "6" "0")"

xxd로 확인하세요:

$ printf '%b' "$(printf '\\U%0*X' "6" "0")" | xxd
0000000: 00

경고하다: 4.3 이하의 Bash는 utf-8에서 U0080과 U00FF 사이의 값을 올바르게 인코딩할 수 없습니다. 버전 4.3 또는 4.4를 사용하세요.

답변2

나는 계속 노력했고 해결책을 찾았습니다.

#!/bin/bash

X=0

while [ $X -lt 65536 ]; do
    HEX=`bc <<< "obase=16; $X"`
    HEX="0x${HEX}"
    UCODE=`printf "%0*x\n" 4 $HEX`
    printf "Unicode ${UCODE} = \u${UCODE}\n"
    X=$((X + 1))
done                                                        

나는 이런 식으로 printf를 시도하려고 생각했습니다. https://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux

나는 여전히 좀 더 우아한 해결책을 보고 싶습니다.

답변3

다른 방법으로 이 작업을 수행할 수 있습니다(bash는 u에서 이스케이프된 백슬래시를 무시하는 것 같기 때문입니다 "\u").

#!/bin/bash

X=0

while [ $X -lt 65536 ]; do
    HEX=$(bc <<< "obase=16; $X")
    HEX="0x${HEX}"
    UCODENAME=$(printf "%0*x\n" 4 $HEX)
    UCODECHAR="\\u$(printf "%0*x" 4 $HEX)"
    echo -e "Unicode ${UCODENAME} = ${UCODECHAR}"
    X=$((X + 1))
done

물론 스크립트는 여전히 bash에만 적용됩니다. 기타 의견:

  • 대부분의 사람들은 백틱보다는 $(and를 사용하는 것을 권장합니다 .)
  • bash는 printf유니코드를 직접 인쇄할 수 있습니다(에코가 필요하지 않음).
  • 추가 printf항목은 UCODECHAR중복됩니다.

중복 제거:

#!/bin/bash

X=0

while [ $X -lt 65536 ]; do
    HEX=$(bc <<< "obase=16; $X")
    HEX="0x${HEX}"
    UCODENAME=$(printf "%0*x\n" 4 $HEX)
    UCODECHAR="\\u${UCODENAME}"
    echo -e "Unicode ${UCODENAME} = ${UCODECHAR}"
    X=$((X + 1))
done

관련 정보