【问题标题】:Script for Hex to ASCII Text Converter十六进制到 ASCII 文本转换器的脚本
【发布时间】:2020-04-06 05:21:48
【问题描述】:

我正在尝试将十六进制数字转换为 ASCII 文本,为此我使用了xxd。但问题是它没有抛出任何输出。

例如,我用过:

echo 86973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D | xxd -r -p

但它没有给我任何输出。

如果没有在线生成器的帮助,还有其他方法可以隐藏这个吗?请帮忙!!

【问题讨论】:

    标签: bash echo xxd


    【解决方案1】:

    您的十六进制数据有许多 CR (0D) 字节,这会导致光标回退到行首并覆盖任何先前的输出。此外,当管道运行完毕后,您的 shell 提示符将覆盖任何剩余的输出。

    您很可能希望通过将 | tr '\r' '\n' 附加到管道来将 CR 转换为 LF 以查看输出:

    $ echo 686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D | xxd -r -p | tr '\r' '\n'
    history 
    ls -ltr 
    n netstats
    n info 
    n status
    exit
    

    【讨论】:

    • 非常感谢您的帮助。这是有道理的。
    • 不客气。如果您找到任何解决您问题的答案,请随时投票(▲)和/或接受它(✔︎)。
    • 或者:<<<'686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D' xxd -r -p | stringsstrings 确保丢弃不可打印的字符。
    • @LéaGris 这比您评论的答案更好地回答了这个问题(也许添加为另一个答案?)
    • @LéaGris 我不确定 OP 是否希望丢弃所有不可打印的字符,因为 OP 没有指定十六进制数据的性质或来源。也许有可能需要保留的终端控制字符。此外,strings 可能不会保留带有 utf-8 字符的字符串。
    【解决方案2】:

    您实际上可以使用printfsed 来分割每2 个字符并以您需要的任何格式输出。您使用 sed 创建一个以换行符分隔的 2 个字符的字符串列表,并通过作为字符串输出来避免控制字符转换问题,例如0D 等...您可以使用 printf "0x%s\n"(通过 printf 处理每一行输入将导致所有 2 字符值的输出)

    例如你可以这样做:

    printf "0x%s\n" $(echo "686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D" |
    sed 's/\(..\)/\1\n/g')
    

    或带有 herestring 的等价物(仅限 bash)

    printf "0x%s\n" $(sed 's/\(..\)/\1\n/g' <<< "686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D")
    

    输出

    0x68
    0x69
    0x73
    0x74
    0x6F
    0x72
    0x79
    0x20
    0x0D
    0x6C
    0x73
    0x20
    0x2D
    0x6C
    0x74
    0x72
    0x20
    0x0D
    0x6E
    0x20
    0x6E
    0x65
    0x74
    0x73
    0x74
    0x61
    0x74
    0x73
    0x0D
    0x6E
    0x20
    0x69
    0x6E
    0x66
    0x6F
    0x20
    0x0D
    0x6E
    0x20
    0x73
    0x74
    0x61
    0x74
    0x75
    0x73
    0x0D
    0x65
    0x78
    0x69
    0x74
    0x0D
    

    如果您想要小写十六进制的值,那么您实际上可以使用"0x%02x" 转换将输入值处理为十六进制:

    printf "0x%02x\n" $(echo "686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D" |
    sed 's/\(..\)/0x\1\n/g')
    

    输出

    0x68
    0x69
    0x73
    0x74
    0x6f
    0x72
    0x79
    0x20
    0x0d
    0x6c
    0x73
    0x20
    0x2d
    0x6c
    0x74
    0x72
    0x20
    0x0d
    0x6e
    0x20
    0x6e
    0x65
    0x74
    0x73
    0x74
    0x61
    0x74
    0x73
    0x0d
    0x6e
    0x20
    0x69
    0x6e
    0x66
    0x6f
    0x20
    0x0d
    0x6e
    0x20
    0x73
    0x74
    0x61
    0x74
    0x75
    0x73
    0x0d
    0x65
    0x78
    0x69
    0x74
    0x0d
    

    这取决于你想要的输出可能是你所需要的。如果您需要稍微不同的输出格式,请告诉我,我很乐意为您提供进一步帮助。

    或者——如果我把它倒过来,并且你真的想要字符串中每个字符的 ASCII 值,你可以使用一个简单的for 循环和printf 来打印每个字符的 ASCII 值。要输出 ASCII 值,请在双引号变量名称前加上单引号,例如

    a="686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D"
    for ((i = 0; i < ${#a}; i++)); do printf "%s - 0x%02x\n" "${a:i:1}" "'${a:i:1}"; done
    

    输出

    每个字符的字符和ASCII值:

    6 - 0x36
    8 - 0x38
    6 - 0x36
    9 - 0x39
    7 - 0x37
    3 - 0x33
    7 - 0x37
    4 - 0x34
    6 - 0x36
    F - 0x46
    7 - 0x37
    2 - 0x32
    7 - 0x37
    9 - 0x39
    2 - 0x32
    0 - 0x30
    0 - 0x30
    D - 0x44
    6 - 0x36
    C - 0x43
    7 - 0x37
    3 - 0x33
    2 - 0x32
    0 - 0x30
    2 - 0x32
    D - 0x44
    6 - 0x36
    C - 0x43
    7 - 0x37
    4 - 0x34
    7 - 0x37
    2 - 0x32
    2 - 0x32
    0 - 0x30
    0 - 0x30
    D - 0x44
    6 - 0x36
    E - 0x45
    2 - 0x32
    0 - 0x30
    6 - 0x36
    E - 0x45
    6 - 0x36
    5 - 0x35
    7 - 0x37
    4 - 0x34
    7 - 0x37
    3 - 0x33
    7 - 0x37
    4 - 0x34
    6 - 0x36
    1 - 0x31
    7 - 0x37
    4 - 0x34
    7 - 0x37
    3 - 0x33
    0 - 0x30
    D - 0x44
    6 - 0x36
    E - 0x45
    2 - 0x32
    0 - 0x30
    6 - 0x36
    9 - 0x39
    6 - 0x36
    E - 0x45
    6 - 0x36
    6 - 0x36
    6 - 0x36
    F - 0x46
    2 - 0x32
    0 - 0x30
    0 - 0x30
    D - 0x44
    6 - 0x36
    E - 0x45
    2 - 0x32
    0 - 0x30
    7 - 0x37
    3 - 0x33
    7 - 0x37
    4 - 0x34
    6 - 0x36
    1 - 0x31
    7 - 0x37
    4 - 0x34
    7 - 0x37
    5 - 0x35
    7 - 0x37
    3 - 0x33
    0 - 0x30
    D - 0x44
    6 - 0x36
    5 - 0x35
    7 - 0x37
    8 - 0x38
    6 - 0x36
    9 - 0x39
    7 - 0x37
    4 - 0x34
    0 - 0x30
    D - 0x44
    

    【讨论】:

      【解决方案3】:

      您可以使用 python3 inline 打印 ASCII 字符。这可能不像其他答案那样模仿 xxd 输出,但允许您查看导致问题的 \r\n 类型字符。

      $ str='686973746F7279200D6C73202D6C7472200D6E206E657473746174730D6E20696E666F200D6E207374617475730D657869740D'
      $ python3 -c "b=b''.fromhex('$str'); s=str(b)[2:-1]; print(s)"
      history \rls -ltr \rn netstats\rn info \rn status\rexit\r
      

      这里,

      • b=b''.fromhex('$str') 将十六进制数字转换为字节对象。如果你用过 python,对于像换行符这样的字符
      • str(b)[2:-1] 将类似于 b'abcd' 的字节对象转换为 abcdb's 对于输出并不重要,因此会被截断。
      • 如果您想替换@rtx13 的答案中的\r,请添加s.replace('\r', '=n')

      其他 bash 使用说明

      发送到 xxd 时,您的输出中可能会出现额外的换行符。 echo 在输出中添加一个换行符。演示:

      $ echo '' | xxd
      00000000: 0a
      

      如果您不想在管道中添加字节,请使用 printf 获取更多 consistent behavior

      【讨论】:

        猜你喜欢
        • 2014-06-22
        • 1970-01-01
        • 2015-05-22
        • 1970-01-01
        • 2018-01-12
        • 2011-11-27
        • 2011-04-04
        • 2012-11-14
        • 2016-04-22
        相关资源
        最近更新 更多