bashでは、Unicodeコードポイント[0-9A-F]を印刷可能な文字に変換するにはどうすればよいですか?


23

Unicodeコードポイントのリストはありますが、これらの16進値を実際の文字に変換する「簡単な」方法を知りません...

zshにはがあると聞きましたがecho -e '\u0965'bash 4.1 を使用しています。

bashの場合、zshメソッドのような単純なものはありますか?


回答:


16

GNU coreutilsのbashのechoまたは/ bin / echoをiconvと組み合わせて使用​​できます。

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

デフォルトでは、iconvはロケールエンコーディングに変換されます。おそらく、特定のシェルまたはエコーコマンドに依存するよりも移植性が高いのはPerlです。私が知っているほとんどのUNIXシステムはPerlが利用可能であり、いくつかのWindowsポートさえ持っています。

perl -C -e 'print chr 0x0965'

ほとんどの場合、これを行う必要があるのは、Vim / GVimのような組み込みのサポートを備えたエディターです。挿入モードで、Ctrl-Vに続いてuを押し、4つの16進文字を入力します。U + FFFFを超える文字が必要な場合は、大文字のUを使用して8桁の16進文字を入力します。Vimは、キーマップの作成が簡単なカスタムもサポートしています。一連の文字を別のシンボルに変換します。たとえば、wwwと呼ばれる開発したキーマップがあり、TMを™に、(C)を©に、(R)を®に変換します。それが必要になったときのためにクリンゴンのキーマップも持っています。Emacsにも似たようなものがあるはずです。GVimとGNOMEターミナルを含むGTK +アプリを使用している場合は、Ctrl-Shift-uに続いて4桁の16進数文字を使用してUnicode文字を作成できます。KDE / Qtにも似たようなものがあるはずです。

更新: Bash 4.2現在、組み込み機能のようです。

echo $'\u0965'

更新:また、最近ではPythonの例がおそらくPerlよりも好まれます。これはPython 2と3の両方で機能します:

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

おかげで...素晴らしく、簡潔でperlの1が、それは少しそれがUTF-16BEとして値を処理するために知っているかのよう困惑私を持っている..私はそれの何が「CHR」と...推測する
Peter.O

@fredそれは良い点です。Perlの例はロケールに依存します。-Cは完全なUnicode処理を有効にしますが、ロケールはUnicodeの例を使用しているため、この例は機能します。LANGをCに設定すると、印刷中のワイド文字に関する警告が表示されますが、それでも印刷されます。chr 0xa2UTF-8ロケールで印刷する場合、セント記号¢を取得しますが、LANG = Cを使用する場合、UTF-8では無効なバイト0xa2を印刷するため、 を取得します。Vim / GVimの例は、ロケールにわずかに依存します。より正確には、ファイルのエンコードに。UTF-8以外のロケールでVimを起動した場合、次のことが必要になります:set encoding=utf-8
penguin359

@fred指摘すべきは、PerlはUTF-8のようなUnicodeロケールで開始された場合、chrの値をUnicodeコードポイントとして扱います。コードポイントは、文字を表す一意の番号であり、UTF-16BEやUTF-8などのいずれのエンコーディングにも関連付けられていません。印刷時に正しいエンコードに変換します。たとえば、楔形記号AはコードポイントU + 012000です。chr 0x12000Perlでそれを表現するために使用できます(Unicodeがアクティブであると仮定)。UTF-16BEでは、これは0xd8、0x08、0xdc、および0x00です。あなたのキャラクターはU + 0965で、これはたまたまバイト0x09にUTF-16BEで0x65が続いたものです。
ペンギン359

@ penguin359 ..ありがとう、いつか(うまくいけば)perlをよく見るでしょう..それは計り知れないほど不可解なようですが、最初はsedとregexもそうでしたが、今はかなり簡単です...多分少しvimのような; 急な学習曲線、そして普通のセーリング....あなたの説明を読むのは良いことです...それは道を開く..
Peter.O

スティーブンDの printf soultionがUnicode範囲のASCIIブロックを処理しないことを(再)発見したので、あなたのperl答えは(私の特定の要件のために)最高です。 、しかし、私はそれを忘れていました。ここではその限界についてqueston /答えは...であるUnicodeのコードポイントなぜprintfのレポートは、すべてが、3(ASCII-範囲)にエラーがない
Peter.O

13

バッシュ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.

ありがとう...私はまだ主にUbuntu 10.04でbash 4.1.5を使用していますが、4.2で利用可能になったことを知っているのは確かに良いことです。(+1)
Peter.O

1
+1; bash 4.2.xバージョンには、0x80から0xff128 - 255)までの値、つまり拡張ASCII範囲の値が正しくUTF8エンコードされておらず、代わりに通過するだけのバグがあることに注意してください?。(少なくとも)現在、4.3.11これは修正されています。echo $'\ued'rendersの場合í、バグは存在しません
mklement0

5

GNU coreutilsを使用している場合は、以下を試してくださいprintf

$ printf '\u0965\n'

echo コンソールがUTF-8を使用していて、UTF-8エンコーディングを使用している場合、ジョブを実行できます。

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

Unicode to UTF-8 hex encodingsの表は、http//www.utf8-chartable.de/にあります。多数のスクリプト言語を使用して、Unicodeコードポイントを16進数に変換できます。Pythonを使用した例を次に示します。

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を使用している場合は、それらを使用して文字を印刷することもできます。


ありがとう。echoコードポイントは2バイトのUTF-16ビッグエンディアンなので、私が望むことはできませんが、2つの printf関数があることを思い出しました!(私はprintfがそれを行うことができると思っていたので、間違ったものを呼び出しているようです)... $(which printf)動作します... Pythonの例のおかげで..しかしこれ(私の学習曲線)のために、私は近くに固執しようとしていますできる限り「bash」することができます。(bashに十分慣れると、Pythonに夢中になります...ところで、.encode('hex')必要なものを超えた一歩です。少し忙しい:)
Peter.O

ええ、.encode( 'hex')は、私にとってエコーで動作するように見える16進コードを取得するためのものでした。これの少なくとも一部が役立ったことを嬉しく思います。
スティーブンD

perlスニペットを見ました。ありがとう...これらのさまざまなソリューションを表にしておくのは良いことです... printfはまさに私が探していたものです(zshの例のように、1つのコマンド)... ..私はよく私の投稿があり、使用していない-他のスクリプティング言語進データのストリーム上で動作する方法(なし\ 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

更新:これは、単一のUnicode値を実行するbashの方法です...(「bash」による意味:別のスクリプト言語を使用しない)..このaskubuntu Q / AのサジェストについてGillesに感謝します。このリンクに
よると:recode(Obsoletes iconv、dos2unix、unix2dos).. 編集:ただし、以下のコメントに従って、「obsoletes」は単に「代替」を意味する場合があります

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

入力として生の 16進ダンプを処理する方法を次に示します(つまり、\ u0965、および\ x09 \ x65などのエスケーププレフィックスなし)..
xxdvim-common、生の16進ダンプを元に戻すことができる16進ダンプユーティリティ(パッケージ化されています)です。ダンプが表す文字に... UnicodeコードポイントはUTF-16BigEndianです。これは16進ダンプとまったく同じです。
xxd復帰モードでは、改行付きの16進値のストリームを受け入れます。これは無視されます。

このスクリプトはUTF-16BEストリームを作成し、それを元の文字に戻します。
最後の行には、必要な2つのコマンドが含まれています。xxdそしてiconv

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 hex-dump入力を表示)。
注意; xxd独自の出力を60桁の16進数の改行でセグメント化します... revertオプションは、これらの改行を無視します。

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

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

回答でpenguin359の情報を使用したように見えるので、彼の回答を私のものではなく正しいものとしてマークすることを検討してください。
スティーブンD

@Steven D:注目に値するコメントですが、 "seem"は有効な言葉です。私はこのようなiconvを数日間使用していますが、単一のコマンドがあるかどうか疑問に思いました。Windows(C ++)で同様のファイル全体の処理を行ったので、Unicodeを理性的に理解しています。私は本当に素早く簡単なbash方法を求めていました。「bash」とは、bashスクリプト言語を使用することです。bash内からのpython / perlではありません)。このページを読んでいる人にとって何らかの価値があるかもしれないので、これを答えとして追加しました。ファイル全体に適したワンライナーです。あなたprintfにとって最高の答えです。
Peter.O

2
recodeはiconvを廃止するとは言いません。実際、recodeはiconvよりも古く、最近ではiconvはrecodeよりもデフォルトではるかに一般的にインストールされます(たとえば、Linuxでは、libcに付属するためiconvがほとんど常にインストールされます)。
ジル 'SO-悪であるのをやめる'

ありがとう。私はそれについて疑問に思っていた..そのウェブページは正確な参照ではありません...だから、それはより多くの代替手段です
...-Peter.O

1

OSのデフォルトエンコーディングがUTF-8(現在のほとんどのディストリビューションに当てはまる)であると仮定すると、bashを直接使用してUNICODEコードポイントを変換できます。

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

もちろん、グリフは正しいフォントを持っている場合にのみ正しく表示されます。bash 4.3以降、すべてのコードポイントが正しく機能します。また、この2つの組み込みオプションも機能します。

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

bash 4.2では、0x80to からのUnicodeコードポイント0xFFが正しくエンコードされないことに注意してください(bashのバグ)。この問題を回避するには、このサイトのプログラムを確認する必要があります(数値を文字に変換する問題を詳しく調べるのにも適しています)。


bash 4.3およびzshで動作します。リンクできるbash 4.2のバグレポートはありますか?
ミケル

これは正しいバグのように見えます: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-マンは「元に戻すモニカ言う
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.