2009-10-22 205 views
42

可以说我有一个字符串5a。这是ASCII 字母Z的十六进制表示。我需要知道一个Linux shell命令,它将采用十六进制字符串 并输出字符串表示的二进制字节。linux shell脚本:十六进制字符串到字节

所以,如果我做

echo 5a | command_im_looking_for > temp.txt 

和我开temp.txt,我会看到一个孤立的字母Z

回答

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

注意,这不会跳过非十六进制字符。如果你只想十六进制(没有从原来的字符串等空格):

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

此外,zshbash支持这一本身在echo

echo -e '\x5a' 
+0

你可能需要把“我”后的正则表达式那里。 – 2009-10-22 02:57:34

+0

哎呦,谢谢:) – bdonlan 2009-10-22 02:58:13

+0

或者把a-fA-F放在字符类中。 – 2009-10-22 02:58:33

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

将'print'更改为'sys.stdout.write'以防止多余的换行字符。 – nobar 2013-07-10 19:46:43

-3

OD -c 或 hexdump -c

+4

不,这会转换到另一个方向(字符为八进制或十六进制)。 – 2009-10-22 07:09:40

+0

检查语法。 -c给出字符输出。 -a只给ascii。我通常用它来查看未知文件,例如“od -c filename | more”,它会将文件以可读的字符倾倒出来 – james 2009-10-22 12:44:56

+2

您能否提供一个可用的示例?看起来,这会以字符形式转储输入流,但不会将基于十六进制的数字作为输入 - 因此它不提供所需的功能。 – nobar 2013-07-10 19:51:11

3

根据你得到那个“5a”的位置,你可以直接追加\ x并传递给printf

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

第二行和第三行可以合并为一个:'printf'\ x $ {a}“' – 2009-10-22 07:11:50

64

用来做此使用XXD

echo -n 5a | xxd -r -p 

但是,我意识到,在于Debian/Ubuntu,XXD是VIM-共同的一部分,因此可能不存在于一个最小的系统。也避免Perl的(恕我直言,还没有一个最小系统的一部分),我结束了使用SED,xargs的和printf这样的:

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

主要是我只是想转换几个字节,它的好了这样的任务。这种解决方案优于ghostdog74的优点是,它可以自动转换任意长度的十六进制字符串。使用xargs是因为printf不从标准输入中读取数据。

+0

或直接输入:printf'\ x5a' – Vouze 2014-07-30 08:36:04

+0

@Vouze我的答案的哪个方面是您的评论应该解决的问题? – josch 2014-07-30 12:04:34

+1

该死的,我知道这是在3年后的复杂答案,但我没有线索xxd存在。由于我现在遇到的问题,我一直需要它......恒定的十六进制字节字符串从调试器转储。是的,@Vouze的评论是该死的毫无意义。 – 2014-09-02 13:39:20

10

你可以通过回声而不是其他的东西。不要忘记添加“-n”,否则您将自动获得换行符:

echo -n -e "\x5a" 
+1

不回答上面提到的问题,但回答了当我在这里搜索谷歌发送给我的问题:-)(btw。发送输出到| hexdump -C有助于识别不需要的换行符等) – JepZ 2015-05-09 13:32:12

0

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 

如果你ar È处理ASCII外的字符,并且你将是编码所得到的字符串 Base64的,则可以禁用UTF-8与-b

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

这里是一个纯bash脚本(如printf是一个bash内建) :

#warning : spaces do matter 
die(){ echo "[email protected]" >&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已经运行,这应该比启动新进程的任何其他解决方案都快。

+0

略短:' for((i = 0; i <$ {#p}; i + = 2)); do p2 + = \\ x $ {p:$ i:2}; done' – starfry 2014-11-10 18:45:14

7

猛砸一个班轮

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

这似乎并不适用于多线程,字节消息...当我运行 'echo -n“0102abcd”|同时读取-n 2代码;做printf“\ x $ code”;完成| hexdump' 产量 '0201 cdab' – 2016-03-02 19:15:07

+1

@约翰钢似乎hexdump都显示数据作为默认在十六进制数字字。试试这个'echo -n“0102abcd”|同时读取-n 2代码;做printf“\ x $ code”;完成| hexdump -e'/ 1“%02x”''' – user3132194 2016-03-03 05:28:32

1

DC可以数字基地之间进行转换:

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

一些python3单行与任何字节数工作。

解码十六进制(含strip,所以它的确定有标准输入一个换行符):

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

编码(十六进制)

$ echo foo | python3 -c "import sys, binascii; print(binascii.hexlify(sys.stdin.buffer.read()).decode())" 
666f6f0a 
+0

只需在解码hex时使用print命令,你就可以看到ctrl chars,null chars,e.t.c .. 'echo 666f6f0a62617200 | python3 -c“import sys,binascii; print(binascii.unhexlify(input()))”'OUTPUT: 'b'foo \ nbar \ x00'' – gaoithe 2016-01-12 12:03:23

相关问题