U + xxxxx 코드로 지정된 이모티콘을 utf-8로 변환하는 방법은 무엇입니까?


16

이모티콘은 U + xxxxx 형식을 사용하여 지정된 것 같습니다.
여기서 각 x는 16 진수입니다.

예를 들어 U + 1F615 는 "혼란 된 얼굴"에 대한 공식 유니 코드 컨소시엄 코드 입니다.

나는 종종 혼란스러워서이 상징에 대해 강한 친근감을 가지고 있습니다.

U + 1F615 I 유니 코드 문자 만 가능한 인코딩은 8, 16, 24 또는 32 비트가 필요하기 때문에 생각 5 16 진수는 5 × 4 = 20 비트가 필요한 반면, 표시 나에게 혼동된다.

이 기호가 bash에서 완전히 다른 16 진수 문자열로 표시되는 것으로 나타났습니다.

$echo -n 😕 | hexdump
0000000 f0 9f 98 95                                    
0000004

$echo -e "\xf0\x9f\x98\x95"
😕

$PS1=$'\xf0\x9f\x98\x95  >'
😕  >

U + 1F615\ x00 \ x01 \ xF6 \ x15 와 같은 것으로 변환 될 것으로 예상했을 것 입니다.

이 두 인코딩 사이의 관계가 보이지 않습니까?

공식 유니 코드 컨소시엄 목록 에서 심볼 을 찾을 때이 지루한 방식으로 수동으로 변환하지 않고도 해당 코드를 직접 사용할 수 있기를 원합니다. 즉

  • 일부 웹 페이지에서 심볼 찾기
  • 웹 브라우저의 클립 보드에 복사
  • 16 진 덤프를 통해 에코하여 리얼 코드를 발견하기 위해 bash에 붙여 넣습니다.

이 20 비트 코드를 사용하여 32 비트 코드가 무엇인지 확인할 수 있습니까?

이 두 숫자 사이에 관계가 있습니까?

답변:


20

UTF-8유니 코드 의 가변 길이 인코딩 입니다. ASCII 슈퍼 세트로 설계되었습니다. 인코딩에 대한 자세한 내용은 Wikipedia 를 참조하십시오 . \x00 \x01 \xF6 \x15UCS-4BE또는 UTF-32BE인코딩.

로케일의 charmap이 UTF-8 (의 출력 참조 locale charmap) 인 경우 유니 코드 코드 포인트에서 UTF-8 인코딩으로 가져 오려면 다음과 같습니다.

$ printf '\U1F615\n'
😕
$ echo -e '\U1F615'
😕
$ confused_face=$'\U1F615'

후자 는 POSIX 표준의 다음 버전에있을 것입니다 .

AFAIK는, 그 구문은 독립 실행 형 GNU에 의해 2000 년에 도입 printf합니다 (반대 유틸리티 printf에 가져온 GNU 쉘 유틸리티) echo/ printf/ $'...'첫 번째 내장 명령 에 의해 zsh2003 년에 불구하고 2010 년, 2004 년의 경우 ksh93, bash는 ( 제대로가 작동하지 2014 년까지 )이지만 다른 언어에서 영감을 얻은 것 같습니다.

ksh93또한으로 지원 printf '\x1f615\n'하고 printf '\u{1f615}\n'.

$'\uXXXX'$'\UXXXXXXXX'지원하는 zsh, bash, ksh93, mksh와 FreeBSD sh, GNU printf, GNU echo.

POSIX는 더 적은 자릿수를 허용하므로 향후 버전에서는 변경 될 가능성이 있지만 일부는 모든 자릿수 (와 \U0001F615반대로 \U1F615) 가 필요합니다 . (가) 경우 어떤 경우에, 당신은 모든 숫자를 필요 \UXXXXXXXX와 같이 16 진수 다음에 될 \U0001F615FOX대로 \U1F615FOX했을 것이다 $'\U001F615F'OX.

일부는 문자열이 구문 분석 될 때 또는 확장 될 때 현재 로케일 인코딩의 문자로 확장되며 일부는 로케일에 관계없이 UTF-8로만 확장됩니다. 현재 로캘의 인코딩에서 문자를 사용할 수없는 경우 동작은 셸마다 다릅니다.

따라서 최상의 이식성을 위해 UTF-8 로케일에서만 사용하고 모든 숫자를 사용하고 다음에서 사용하는 것이 가장 좋습니다 $'...'.

printf '%s\n' $'\U0001F615'

참고 :

LC_ALL=C.UTF-8; printf '%s\n' $'\U0001F615'

또는:

{
  LC_ALL=C.UTF-8
  printf '%s\n' $'\U0001F615'
}

(을 포함한 모든 쉘에서 작동하지 않음 bash(가) 때문에) $'\U0001F615'되어 구문 분석 하기 전에 LC_ALL할당됩니다. (또한 시스템 로케일라는 하리라는 보장이 없다 있습니다 C.UTF-8)

필요한 것 :

LC_ALL=C.UTF-8; eval "confused_face=$'\U0001F615'"

또는:

LC_ALL=C.UTF-8
printf '%s\n' $'\U0001F615'

(복합 명령 또는 기능 내에 있지 않음).


반대로 UTF-8 인코딩에서 유니 코드 코드 포인트로 가져 가려면 이 다른 질문 이나 질문을 참조하십시오 .

$ unicode 😕 
U+1F615 CONFUSED FACE
UTF-8: f0 9f 98 95  UTF-16BE: d83dde15  Decimal: 😕
😕
Category: So (Symbol, Other)
Bidi: ON (Other Neutrals)

$ perl -CA -le 'printf "%x\n", ord shift' 😕
1f615

2
\U1F615유효한 다른 16 진수가 뒤에 오는 경우 이스케이프 시퀀스의 일부로 간주됩니다. 뒤에 오는 내용에 관계없이 작동하려면 정확히 8 자리가되기에 충분한 선행 0이 있어야합니다.\U0001F615
kasperd

@kasperd, 감사합니다. 예, 주목할 가치가 있습니다. 나는 그것을 대답에 포함시켰다.
Stéphane Chazelas

7

다음은 UTF-32 (빅 엔디안)에서 UTF-8로 변환하는 방법입니다

$ confused=$(echo -ne "\x0\x01\xF6\x15" | iconv -f UTF-32BE -t UTF-8)     
$ echo $confused 
😕

0x01F615거기에 16 진수 값 이 있고 32 비트를 채우기 위해 추가 0이 채워져 있음을 알 수 있습니다 .

UTF-8 의 Wikipedia 페이지 는 유니 코드 코드 포인트에서 UTF-8 표현으로의 변환을 매우 명확하게 설명합니다. 그러나 쉘 스크립팅에서 직접 시도하는 것이 가장 좋은 아이디어는 아닙니다.

UTF-32 는 고정 너비이며 코드 포인트와 UTF-32 표현 간의 대응은 사소합니다. 값은 동일합니다.


6

머리 나 종이에 좋은 방법 :

  1. 얼마나 많은 바이트가 될지 알아보십시오. U + 0080의 값은 1 바이트이고, U + 0800의 값은 2 바이트이고, U + 10000의 경우 3 바이트, 그렇지 않으면 4 바이트입니다. 귀하의 경우에는 4 바이트입니다.

  2. 16 진수를 8 진수로 변환하십시오 0373025.

  3. 끝에서 시작하여 한 번에 2 개의 8 진수를 제거하여 일련의 8 진수 값을 얻으십시오 037 030 025.

  4. 예상 바이트 수보다 8 진수 값이 적은 경우 시작 부분에 0을 더 추가하십시오 000 037 030 025.

  5. 첫 번째를 제외하고는 다음을 추가 0200하십시오 000 0237 0230 0225.

  6. 첫 번째로 0300예상 길이가 2, 03403 또는 03604 인 경우 다음을 추가하십시오 360 0237 0230 0225.

이제 8 진 이스케이프 문자열로 작성하십시오 \360\237\230\225. 원하는 경우 선택적으로 16 진으로 다시 변환하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.