简体   繁体   English

Bash。 十六进制到ASCII。 没有 xxd 或 perl 是否可行?

[英]Bash. Hex to ascii. Is possible without xxd or perl?

I'm developing a script on which I have a hex string 31323334353637383930313233 and I want to transform it into ASCII.我正在开发一个脚本,上面有一个十六进制字符串31323334353637383930313233 ,我想将其转换为 ASCII。 Desired output is 1234567890123 .所需的 output 是1234567890123

I already have it working using:我已经使用它工作了:

echo "31323334353637383930313233" | xxd -r -p

or或者

echo "31323334353637383930313233" | perl -pe 's/(..)/chr(hex($1))/ge'

But the point is try to use the minimum possible requirements for the script.但重点是尽量使用脚本的最低要求。 I want it working in suse, fedora, debian, ubuntu, arch, etc... It seems the xxd command is included in vim package. I want it working in suse, fedora, debian, ubuntu, arch, etc... It seems the xxd command is included in vim package. I'm wondering if there is a way to achieve this using only awk or any internal Linux tool which is going to be present by default in all Linux systems.我想知道是否有一种方法可以仅使用 awk 或任何内部 Linux 工具来实现此目的,该工具将默认出现在所有 Linux 系统中。

Thank you.谢谢你。

Found this script here : 在这里找到此脚本:

#!/bin/bash
function hex2string () {
  I=0
  while [ $I -lt ${#1} ];
  do
    echo -en "\x"${1:$I:2}
    let "I += 2"
  done
}
hex2string "31323334353637383930313233"
echo

You may change the line hex2string "31323334353637383930313233" so that it takes the hex value from parameters, that is: 您可以更改行hex2string "31323334353637383930313233" ,以使其从参数中获取十六进制值,即:

#!/bin/bash
function hex2string () {
  I=0
  while [ $I -lt ${#1} ];
  do
    echo -en "\x"${1:$I:2}
    let "I += 2"
  done
}
hex2string "$1"
echo

So when executed as: 所以当执行为:

./hexstring.sh 31323334353637383930313233

It will provide the desired ascii output. 它将提供所需的ascii输出。

NOTE: Can't test if it works in all Linux systems. 注意:无法测试它是否适用于所有Linux系统。

Using , from HEX to ASCII 使用 ,从HEXASCII

$ gawk  '{ 
           gsub(/../,"0x& "); 
           for(i=1;i<=NF;i++)
              printf("%c", strtonum($i)); 
           print "" 
}' <<<"31323334353637383930313233"
1234567890123

Using any 使用任何

$ cat hex2asc_anyawk.awk 
BEGIN{
    split("0 1 2 3 4 5 6 7 8 9 A B C D E F", d, / /)
    for(i in d)Decimal[d[i]]=i-1
}

function hex2dec(hex,  h,i,j,dec)
{ 
    hex = toupper(hex);                
    i   = length(hex);                 
    while(i)
    {  
          dec += Decimal[substr(hex,i,1)] * 16 ^ j++
          i--                          
    }
    return dec;
}
{

    gsub(/../,"& "); 
    for(i=1;i<=NF;i++)
        printf("%d",hex2dec($i));
    print ""
}

Execution 执行

$ awk -f hex2asc_anyawk.awk <<<"31323334353637383930313233"
1234567890123

Explanation 说明

Steps : 脚步 :

  1. Get the decimal equivalent of hex from table. 从表中获取十六进制的十进制等效值。

  2. Multiply every digit with 16 power of digit location. 将每个数字乘以16的数字位置幂。

  3. Sum all the multipliers. 对所有乘数求和。

在此处输入图片说明

Example : 范例:

在此处输入图片说明

BEGIN{
    # Here we created decimal conversion array, like above table
    split("0 1 2 3 4 5 6 7 8 9 A B C D E F", d, / /)
    for(i in d)Decimal[d[i]]=i-1
}

function hex2dec(hex,  h,i,j,dec)
{ 
    hex = toupper(hex);                 # uppercase conversion if any A,B,C,D,E,F
    i   = length(hex);                  # length of hex string
    while(i)
    {  
          # dec var where sum is stored
          # substr(hex,i,1) gives 1 char from RHS
          # multiply by 16 power of digit location 
          dec += Decimal[substr(hex,i,1)] * 16 ^ j++
          i--                           # decrement by 1
    }
    return dec;
}
{
    # it modifies record
    # suppose if given string is 31323334353637383930313233
    # after gsub it becomes 31 32 33 34 35 36 37 38 39 30 31 32 33
    # thus re-evaluate the fields

    gsub(/../,"& "); 

    # loop through fields , NF gives no of fields
    for(i=1;i<=NF;i++)

        # convert from hex to decimal
        # and print equivalent ASCII value 
        printf("%c",hex2dec($i));

    # print newline char
    print ""
}

Meaning of dec += Decimal[substr(hex,i,1)] * 16 ^ j++ dec += Decimal[substr(hex,i,1)] * 16 ^ j++含义

dec += Decimal[substr(hex,i,1)] * 16 ^ j++
 ^           ^                    ^
 |           |                    | 
 |           |                    2.Multiply every digit with 16 power of digit location.
 |           |    
 |           1.Gives decimal equivalent of hex
 | 
 | 
 3. Sum all the multipliers 

备用(g)awk解决方案:

echo "31323334353637383930313233" | awk 'RT{printf "%c", strtonum("0x"RT)}' RS='[0-9]{2}'

here's a special cheating trick for u - due to ingenuity of how they originally mapped decimal digits to bytes, their hex are all x3[0-9] ,这是 u 的一个特殊作弊技巧 - 由于他们最初如何将十进制数字映射到字节的独创性,它们的十六进制都是x3[0-9]

so therefore, if u already know they would decode out to digits and nothing else, here's a fast shortcut:因此,因此,如果您已经知道它们会解码为数字而仅此而已,那么这是一个快速的捷径:

 echo "31323334353637383930313233" | 
 mawk 'gsub("..","_&") + gsub("_3",_)^_'
1234567890123

if it's already URL-percent-encoded, then it's even simpler:如果它已经是 URL-percent-encoded,那么它就更简单了:

 echo '%31%32%33%34%35%36%37%38%39%30%31%32%33' | 
 mawk 'gsub("%3",_)^_' or gawk ++NF FS='%3' OFS=
1234567890123

This specialized approach can handle hex of absolutely any arbitrary size, even for awk s that don't have built-in support for bigint s这种专门的方法可以处理绝对任意大小的十六进制,即使对于没有内置支持bigintawk如此

TL;DR : don't "do math" when none is needed

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM