web-dev-qa-db-ja.com

Linuxシェルで16進数をASCII文字に変換するには?

文字列5aがあるとしましょう。

これは、ASCII letter Zの16進表現です。

16進数の文字列を受け取り、その文字列が表すASCII文字を出力するLinuxシェルコマンドを知っている必要があります。

だから私がそうするなら:

echo 5a | command_im_looking_for

単独の文字Zが表示されます。

Z
57
echo -n 5a | Perl -pe 's/([0-9a-f]{2})/chr hex $1/gie'

これは、16進数以外の文字をスキップしないことに注意してください。 16進数だけが必要な場合(元の文字列に空白がないなど):

echo 5a | Perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie'

また、zshおよびbashは、echoでこれをネイティブにサポートします。

echo -e '\x5a'
59
bdonlan

私はxxdを使用してこれを行っていました

echo -n 5a | xxd -r -p

しかし、Debian/Ubuntuでは、xxdはvim-commonの一部であるため、最小限のシステムには存在しない可能性があることに気付きました。また、Perl(私見も最小限のシステムの一部ではない)を避けるために、次のようにsed、xargs、printfを使用することになりました。

echo -n 5a | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf

ほとんどの場合、数バイトだけを変換したいだけで、このようなタスクには問題ありません。 ghostdog74に対するこのソリューションの利点は、任意の長さの16進文字列を自動的に変換できることです。 xargsが使用されるのは、printfが標準入力から読み取らないためです。

84
josch

エコーのみで、他のものなしで作成できます。 「-n」を追加することを忘れないでください。そうしないと、自動的に改行が入ります。

echo -n -e "\x5a"
13
Fa11enAngel

Bashワンライナー

echo -n "5a" | while read -N2 code; do printf "\x$code"; done
9
user3132194

「5a」を取得した場所に応じて、\ xを追加してprintfに渡すことができます。

$ a=5a
$ a="\x${a}"
$ printf "$a"
Z
3
ghostdog74

任意のバイト数で動作するいくつかのpython3ワンライナー。

16進数のデコード(stripを使用して、stdinに改行を入れても問題ありません):

$ echo 666f6f0a | python3 -c "import sys, binascii; sys.stdout.buffer.write(binascii.unhexlify(input().strip()))"
foo

16進数のエンコード:

$ echo foo | python3 -c "import sys, binascii; print(binascii.hexlify(sys.stdin.buffer.read()).decode())"
666f6f0a
3
Jack O'Connor

dcは数値ベース間で変換できます。

$ echo 5a | (echo 16i; tr 'a-z' 'A-Z'; echo P) | dc
Z$
2
Roger Willcocks

以下は純粋なbashスクリプトです(printfはbashビルトインであるため):

#warning : spaces do matter
die(){ echo "$@" >&2;exit 1;}

p=48656c6c6f0a

test $((${#p} & 1)) == 0 || die "length is odd"
p2=''; for ((i=0; i<${#p}; i+=2));do p2=$p2\\x${p:$i:2};done
printf "$p2"

Bashがすでに実行されている場合、これは新しいプロセスを起動する他のソリューションよりも高速です。

2
Vouze
echo 5a | python -c "import sys; print chr(int(sys.stdin.read(),base=16))"
1
unutbu

GNU awk 4.1

awk -niord '$0=chr("0x"RT)' RS=.. ORS=

これにエコーすると、余分なヌルバイトが生成されることに注意してください

$ echo 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000  59  5a  00
          Y   Z  \0

代わりにprintfを使用してください

$ printf 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000  59  5a
          Y   Z

また、GNU awkはデフォルトでUTF-8を生成します

$ printf a1 | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1
0000000 c2 a1

ASCII以外の文字を処理していて、結果の文字列をBase64でエンコードする場合は、-bでUTF-8を無効にできます

echo 5a | sha256sum | awk -bniord 'RT~/\w/,$0=chr("0x"RT)' RS=.. ORS=
0
Steven Penny

@ Randal comment に従って、Perlを使用できます。

$ printf 5a5a5a5a | Perl -lne 'print pack "H*", $_'
ZZZZ

その他の方法:

$ printf ZZZZ | Perl -lne 'print unpack "H*", $_'
5a5a5a5a

ファイルを使用した別の例:

$ printf 5a5a5a5a | Perl -lne 'print pack "H*", $_' > file.bin
$ Perl -lne 'print unpack "H*", $_' < file.bin
5a5a5a5a
0
kenorb

ここでの私の答えに似ています: Linux Shellスクリプト:16進数からバイナリ文字列へ

次のような同じツールを使用して実行できます(5aの代わりにASCII印刷可能文字を使用):

echo -n 616263 | cryptocli dd -decoders hex

次の結果が生成されます。

abcd
0
tehmoon