【问题标题】:Extract UTF-uncoded binary data from JSON using jq使用 jq 从 JSON 中提取 UTF 未编码的二进制数据
【发布时间】:2018-01-13 12:54:34
【问题描述】:

假设我有一个 0xb7 字节编码为 UTF 代码点的 JSON:

{"key":"_\u00b7_"}

如果我用 jq 提取“key”的值,它会保留这个字节的 utf8 编码,即“c2 b7”:

$ echo '{"key":"_\u00b7_"}' | ./jq '.key' -r | xxd
0000000: 5fc2 b75f 0a                             _.._.

是否有任何 jq 命令可以从这个 JSON 中提取解码后的“5f b7 5f”字节序列?

我可以使用 iconv 之类的额外工具来解决这个问题,但它有点难看:

$ echo '{"key":"_\u00b7_"}' | ./jq '.key' -r \
      | iconv -f utf8 -t utf32le \
      | xxd -ps | sed -e 's/000000//g' | xxd -ps -r \
      | xxd
0000000: 5fb7 5f0a                                _._.

【问题讨论】:

    标签: json utf-8 binary hex jq


    【解决方案1】:

    备用

    解决jq之外的字符编码场景:

    虽然您不想要额外的工具,但 iconvhexdump 确实很容易获得 - 当我需要完全了解管道的某些部分时,我经常依赖 iconv,并且 @ 987654325@ 当我想控制这些部分的表示格式时。

    所以另一种选择是:

    jq -njr '{"key":"_\u00b7_"} | .key' | iconv -f utf8 -t UTF-32LE | hexdump -ve '1/1 "%.X"'
    

    结果:

    5FB75F

    【讨论】:

      【解决方案2】:
      def hx:
        def hex: [if . < 10 then 48 + . else  55 + . end] | implode ;
        tonumber | "\(./16 | floor | hex)\(. % 16 | hex)";
      
      {"key":"_\u00b7_"} | .key | explode | map(hx)
      

      产生:

      ["5F","B7","5F"]
      

      “原始字节”(买主警告

      由于 jq 仅支持 UTF-8 字符串,因此您必须使用一些外部工具来获取“原始字节”。也许这更接近你想要的:

      jq -nrj '{"key":"_\u00b7_"} | .key' | iconv -f utf-8 -t ISO8859-1
      

      这会产生三个字节。

      这是一个无图标的解决方案:

      jq -nrj '{"key":"_\u00b7_"} | .key' | php -r 'print utf8_decode(readline());'
      

      【讨论】:

      • 谢谢! “explode”运算符执行实际的“utf8 => codepoint number”解码,之后有多种方法可以处理这些数据。但是,从 jq 来源看来,目前似乎无法获得实际的“5f b7 5f”字节序列(我的意思是只有 3 个字节,而不是十六进制编码的字符串)作为输出,因为 jq 始终确保它正在处理正确的 utf8 字节序列。因此二进制输出应该总是有某种编码(utf8、hex、base64、uri等)。
      猜你喜欢
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      • 2018-01-26
      • 2018-05-11
      • 2020-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多