bash에서 유니 코드 코드 포인트 [0-9A-F]를 인쇄 가능한 문자로 변환하려면 어떻게해야합니까?


답변:


16

GNU coreutils에서 bash의 echo 또는 / bin / echo를 iconv와 함께 사용할 수 있습니다.

echo -ne '\x09\x65' | iconv -f utf-16be

기본적으로 iconv는 로캘 인코딩으로 변환됩니다. 아마도 특정 쉘이나 echo 명령에 의존하는 것보다 이식성이 더 좋습니다. 내가 알고있는 대부분의 UNIX 시스템에는 Perl을 사용할 수 있으며 여러 Windows 포트가 있습니다.

perl -C -e 'print chr 0x0965'

대부분이 작업을 수행해야 할 때 내장 지원 기능이있는 Vim / GVim과 같은 편집기를 사용하고 있습니다. 삽입 모드에서 Ctrl-V를 누른 다음 u를 누른 다음 4 개의 16 진수 문자를 입력하십시오. U + FFFF 이상의 문자를 사용하려면 대문자 U를 사용하고 8 진수 문자를 입력하십시오. Vim은 또한 키맵을 쉽게 만들 수있는 커스텀을 지원합니다. 일련의 문자를 다른 기호로 변환합니다. 예를 들어, www라고 개발 한 키맵이 있는데, TM을 ™로, (C)를 ©로, (R)을 ® 등으로 변환합니다. 필요할 때 Klingon에 대한 키맵도 있습니다. 나는 이맥스가 비슷한 것을 가지고 있다고 확신한다. GVim 및 GNOME 터미널이 포함 된 GTK + 앱을 사용하는 경우 Control-Shift-u 다음에 4 개의 16 진수 문자를 사용하여 유니 코드 문자를 만들 수 있습니다. KDE / Qt에 비슷한 것이 있다고 확신합니다.

업데이트 : Bash 4.2부터는 현재 내장 기능 인 것 같습니다.

echo $'\u0965'

업데이트 : 또한 오늘날 파이썬 예제는 Perl보다 선호됩니다. 이것은 Python 2와 3에서 모두 작동합니다.

python -c 'print(u"\u0965")'

감사합니다 ... 좋은 간결한에서 펄 하나, 그러나 약간은 UTF-16BE와 같은 값을 치료하기 위해 알고있는 방법으로 의아해 저를 가지고는 ... 내가 그의를 추측 무엇 "CHR"수단 ...
Peter.O

@ 프레드 좋은 지적입니다. Perl 예제는 로케일에 민감합니다. -C를 사용하면 전체 유니 코드 처리가 가능하지만 로케일이 유니 코드 예제를 사용하므로 예제가 작동합니다. LANG를 C로 설정하면 인쇄시 와이드 문자에 대한 경고가 표시되지만 여전히 인쇄됩니다. chr 0xa2UTF-8 로케일로 인쇄 하면 센트 기호 ¢가 표시되지만 LANG = C를 사용하면 UTF-8에서 유효하지 않은 바이트 0xa2를 인쇄하므로 가 나타납니다. Vim / GVim 예제는 로케일에 반-민감합니다. 더 정확하게는 파일 인코딩입니다. 비 UTF-8 로켈에서 Vim을 시작한 경우 다음을 수행해야합니다.:set encoding=utf-8
penguin359

@fred Perl이 UTF-8과 같은 유니 코드 로케일에서 시작되면 Perl은 chr의 값을 유니 코드 코드 포인트로 취급합니다. 코드 포인트는 문자를 나타내는 고유 번호이며 UTF-16BE 또는 UTF-8과 같은 하나의 인코딩에 연결되지 않습니다. 인쇄 할 때 올바른 인코딩으로 변환합니다. 예를 들어, 설형 문자 부호 A는 코드 포인트 U + 012000입니다. I 사용할 수 chr 0x12000(유니 가정하면 활성)을 나타내는 데 펄. UTF-16BE에서 이것은 0xd8, 0x08, 0xdc 및 0x00입니다. 문자는 U + 0965이며 UTF-16BE에서 바이트 0x09와 0x65가됩니다.
penguin359

@ penguin359 .. 고마워, 언젠가 (희망적으로) 나는 perl을 잘 볼 것이다. vim처럼; 가파른 학습 곡선, 그리고 평범한 항해 .... 설명을 읽는 것이 좋습니다 ... 그것은 길을 포장합니다.
Peter.O

나는 Steven D의 printf soultion이 유니 코드 범위의 ASCII 블록을 처리하지 않는다는 것을 (재) 발견했습니다.perl 대답은 지금 최고입니다 (내 특정 요구 사항에 대해). 하지만 잊어 버렸습니다. 여기에 한계에 대한 질문과 답변이 있습니다 ... printf가 3 가지 (ASCII- 범위) 유니 코드 코드 포인트를 제외한 모든 오류를보고하는 이유
Peter.O

13

Bash 4.2 (2011 년 릴리스)는 echo -e '\u0965', printf '\u0965'에 대한 지원을 추가 printf %b '\u0965'하고 echo $'\u0965'작동합니다.

http://tiswww.case.edu/php/chet/bash/FAQ :

o   $'...', echo, and printf understand \uXXXX and \UXXXXXXXX escape sequences.

고마워 ... 우분투 10.04에서 bash 4.1.5를 주로 사용하고 있지만 4.2에서 사용할 수 있음을 확실히 알고 있습니다. (+1)
Peter.O

1
+1; 참고 bash 4.2.x버전이 버그가 어디에 값 사이 0x800xff( 128 - 255) - 즉, 확장 된 ASCII 범위 - 제대로 UTF8 인코딩 대신 그냥 단자로 렌더링하는 것이 잘못된 UTF8 숯의 결과를 통해 전달되지 않습니다 ?. (적어도) 4.3.11이 문제는 해결되었습니다. 만약 echo $'\ued'렌더링 í후 버그는 하지 본.
mklement0

5

GNU coreutils가 있다면 다음을 시도하십시오 printf.

$ printf '\u0965\n'

echo 콘솔이 UTF-8을 사용하고 있고 UTF-8 인코딩이있는 경우 작업을 수행 할 수 있습니다.

$ echo -e '\xE0\xA5\xA5'

유니 코드에서 UTF-8 16 진수 인코딩 테이블은 다음에서 찾을 수 있습니다. http://www.utf8-chartable.de/ . 여러 스크립팅 언어를 사용하여 유니 코드 코드 포인트를 16 진수로 변환 할 수 있습니다. 다음은 파이썬을 사용하는 예입니다.

python -c "print(unichr(int('0965', 16)).encode('utf-8').encode('hex'))"

다음은 인수를 올바른 16 진 값으로 변환하는 Perl 스크립트입니다 (여기서 불필요한 괄호).

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Encode;

foreach (@ARGV) {
    say unpack('H*', encode('utf8', chr(hex($_))))
}

예를 들어

./uni2utf 0965
e0a5a5

물론 Perl 또는 Python을 사용하는 경우 문자를 인쇄하는 데 사용할 수도 있습니다.


감사합니다 .. echoCodepoints는 2 바이트 UTF-16 Big-Endian이므로 원하는 작업을 수행하지 않습니다. 그러나 2 개의 printf 함수 가 있음을 상기시켜 주셨습니다 . (나는 printf가 그것을 할 수 있다고 생각했고, 내가 잘못한 것을 불러내는 것 같습니다.) ... $(which printf)작동합니다 ... 파이썬 예제에 감사드립니다. 유일한 scriting 언어 참여로 "bash는"가능한 한 .. (내가 bash는 편안하게 충분히있을 때, 내가 파이썬에 붙어거야 ... BTW, .encode('hex')내가 필요 이상으로 한 단계입니다 .. (나는 그것을보고 생각 약간 바쁘다 :)
Peter.O

예, .encode ( 'hex')는 echo와 함께 작동하는 것처럼 보이는 16 진수 코드를 얻는 것입니다. 이것의 적어도 일부가 도움이 된 것을 기쁘게 생각합니다.
Steven D

방금 펄 스 니펫을 보았습니다. 감사합니다 ... 다양한 솔루션을 표로 작성하는 것이 좋습니다 ... printf는 내가 찾던 것입니다 (zsh 예제에 따라 단일 명령) ... .. 16 진수 데이터 스트림 (\ u 등)에서 작동하는 사용하지 않는 다른 스크립팅 언어 방법을 게시 할 수 있습니다 .
Peter.O

나는 특히 printf위 의 간결함을 좋아 하지만``\ u00A0 ... I've just re-discovered something I already knew (but dropped off the radar)... Here is a Question I asked about 4 months ago; [Why does printf report an error on all but three (ASCII-range) Unicode Codepoints](http://askubuntu.com/questions/20806/why-does-printf-report-an-error-on-all-but-three-ascii-range-unicode-codepoints)... So *penguin359's* perl` 솔루션은 현재 꽤 좋아 보인다 :) 그에게 초록색 표시perl
Peter.O

2

업데이트 : 여기에 단일 유니 코드 값을 수행하는 bash 방법이 있습니다 ... ( "bash"의 의미 : 다른 스크립팅 언어를 사용하지 않음) ..이 askubuntu Q / A 의 제안에 대해 Gilles에게 감사드립니다 . 이 링크
에 따르면 : recode (Obsoletes iconv, dos2unix, unix2dos). 편집 : 그러나 아래 주석에 따라 "obsoletes"는 "alternative"를 의미 할 수 있습니다.

      echo -n 0x0965 |recode UTF-16BE/x4..UTF-8

다음은 원시 16 진 덤프를 입력 으로 처리하는 방법입니다 (예 : \ u0965 및 \ x09 \ x65와 같은 이스케이프 접두어 없음) .. 원시 16 진 덤프를 되돌릴 수
xxd있는 16 진 덤프 유틸리티 (와 함께 패키지 됨 vim-common)입니다. 덤프가 나타내는 문자에 대해 ... 유니 코드 코드 포인트는 UTF-16 BigEndian입니다. 이것은 정확히 16 진 덤프입니다 ..
xxd 되돌림 모드에서는 줄 바꿈으로 16 진 값 스트림을 허용합니다. 무시됩니다.

이 스크립트는 UTF-16BE 스트림을 작성하여 원래 문자로 되돌립니다.
마지막 줄에는 필요한 두 가지 명령이 있습니다. xxdiconv

for line in \
  "Matsuo Basho (1644-1694)" \
  "  pond" \
  "  frog jumps in" \
  "  plop!"
do 
  echo "$line" |iconv -f "$(locale charmap)" -t "UTF-16BE" |xxd -ps -u 
done |
#    (---this is the **revert** code---) 
tee >(xxd -p -u -r |iconv -f "UTF-16BE") ;echo

출력은 다음과 같습니다 (먼저 UTF-16BE 16 진 덤프 입력 표시).
노트; xxd60 개의 16 진수로 개행 문자로 자체 출력을 분할합니다. 되돌리기 옵션은 이러한 개행을 무시합니다. 16 진수가 아니기 때문에 모든 개행을 무시합니다.

004D0061007400730075006F00200042006100730068006F002000280031
003600340034002D00310036003900340029000A
002000200070006F006E0064000A
0020002000660072006F00670020006A0075006D0070007300200069006E
000A
002000200070006C006F00700021000A

Matsuo Basho (1644-1694)
  pond
  frog jumps in
  plop!

답변에 penguin359의 정보를 사용한 것 같으므로 내 답변이 아니라 자신의 답변을 올바른 것으로 표시하는 것이 좋습니다.
Steven D

@Steven D : 주목할만한 주석이지만 "보여"는 실 용어입니다. 나는 며칠 동안 이와 같은 iconv를 사용하고 있는데, 단일 명령이 있는지 궁금해졌습니다. Windows (C ++)에서 비슷한 전체 파일 처리를 수행 했으므로 유니 코드에 대한 합리적인 이해가 있습니다. 나는 정말 빠르고 간단한 bash방법을 따랐습니다. "bash"는 다음을 의미합니다. bash 스크립팅 언어를 사용합니다. bash 내에서 파이썬 / 펄이 아님). 나는이 페이지를 읽는 누군가에게 가치가있을 수 있기 때문에 이것을 대답으로 추가했습니다. 전체 파일에 적합한 하나의 라이너입니다. 당신 printf은 저에게 가장 좋은 대답입니다.
Peter.O

2
나는 recode가 iconv보다 더 이상 사용되지 않는다고 말하지 않을 것입니다. 실제로 recode는 iconv보다 오래되었습니다. 요즘 iconv는 recode보다 기본적으로 훨씬 일반적으로 설치됩니다 (예를 들어, Linux에서 iconv는 libc와 함께 제공되므로 거의 항상 설치됩니다).
Gilles 'SO- 악마 그만'

고마워요 .. 궁금합니다 .. 그 웹 페이지는 정확한 결정이 아닙니다. 그래서 다른 대안이 될 것입니다 ...
Peter.O

1

OS의 기본 인코딩이 UTF-8 (대부분의 최신 배포판에서는 true)이라고 가정하면 bash를 사용하여 유니 코드 코드 포인트를 직접 변환 할 수 있습니다.

echo -e "Unicode Character 'DEVANAGARI DOUBLE DANDA' (U+0965) \U0965"

물론 올바른 글꼴이있는 경우에만 글리프가 올바르게 나타납니다. bash 4.3부터 모든 코드 포인트가 올바르게 작동합니다. 그리고이 두 가지 내장 옵션도 작동합니다.

printf "%b" "Unicode Character (U+0965) \U0965 \n"
echo $'Unicode Character (U+0965) \U0965'

bash는 4.2에서 유니 코드 코드 포인트 참고 0x80로이 0xFF잘못 인코딩 (bash는 버그). 이 문제를 해결하려면 이 사이트 의 프로그램을 살펴 봐야 합니다 (숫자를 문자로 변환하는 문제를 자세히 살펴 보는 것도 좋습니다).


bash 4.3 및 zsh에서 작동합니다. bash 4.2에 대한 버그 보고서가 있습니까?
Mikel

: 올바른 버그 같은 날이 외모 https://lists.gnu.org/archive/html/bug-bash/2012-02/msg00035.html설명 : 사이 \ u와 \ U 잘못 인코딩 값 \ U80과 \ UFF

0

bash 버전 4.2 이상에서 패턴 대체 사용 :

${parameter/pattern/string}

여기에 설명 된대로 http://steve-parker.org/sh/tips/pattern-substitution/

UNICODE_HEX="U+02211"
printf ${UNICODE_HEX/U+/"\U"}


UNICODE_HEX="U+03BB"
printf ${UNICODE_HEX/U+/"\U"}
λ         

1
,주의 에 명시된 바와 같이 이전의 대답 , 이것은 단지 bash는 버전 4.2 (이상)에서 작동합니다. 사실, 이것은 이전 답변에 거의 추가되지 않습니다.
G-Man, 'Reinstate
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.