내 터미널에서 유니코드 문자가 어떻게 보이는지 확인하기 위해 이를 쉘 스크립트로 작성했습니다.
#!/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")")"
cp
dec=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