JQ十六进制字符串转换为ASCII

时间:2018-08-26 08:42:12

标签: string type-conversion jq

我最终在jq中得到一个要在jq中转换为ASCII的十六进制字符串。在外面做这件事还涉及通过多个条件,这使事情变得更加复杂,并且确实会减慢解决方案的速度。

要清楚:它涉及的字符串翻译如下:

"0x4162634b6c6d" -> "AbcKlm"

剥离“ 0x”很容易(。[2:]),我在bash函数中得到了等效结果:

function h2a () 
{ 
    while read s; do
        n=0;
        while [[ "$n" -lt ${#s} ]]; do
            h="${s:$n:2}";
            printf "\x$h";
            n="$(($n+2))";
        done;
    done
}

但是我真的很想在本地jq中做到这一点。我找到了Rosetta JQ,但是无法转换。

感谢您的帮助!

编辑:进步,发现how to access substrings 现在,我如何转换和迭代?

3 个答案:

答案 0 :(得分:3)

您可以使用如下功能:

def decode_hex:
    ("0123456789abcdef"|split("")|with_entries({key:.value, value:.key})) as $hex_map |
    def decode_nybble: $hex_map[ascii_downcase];
    def decode_byte: (.[0:1]|decode_nybble * 16) + (.[1:2]|decode_nybble);
    def pairs: range(0;length;2) as $i | .[$i:$i+2];
    [pairs|decode_byte] | implode;

然后使用它,去掉所有非十六进制字符并将字符串传递进来。

.[2:] | decode_hex

有趣的是,与数组相比,字符串的处理方式非常不同,令我惊讶。您无法直接对其进行索引或对它们执行其他类似数组的操作。通过查看上面定义$hex_mapdecode_byte的方式,可以看出它有多尴尬。

答案 1 :(得分:0)

$ cat q6.jq 
{ "b": 
   [(
     { "a": (split("")) }
     | .a[] 
     | gsub ("a"; "10"; "i") | gsub ("b"; "11"; "i") | gsub ("c"; "12"; "i") | gsub ("d"; "13"; "i") | gsub ("e"; "14"; "i") | gsub ("f"; "15"; "i")
    )
   ]
} 
| { "a": [ .b as $m | range(0; $m | length; 2) | { "q" : [ ($m[.]|tonumber),  ($m[(. + 1)]|tonumber) ] } ] } |
[ (.a[].q) as $b | (($b[0]) * 16) as $d | ($b[1]) as $e | ($d+$e) ] | implode

$ echo '"4162634b6c6d"' | jq -f q6.jq
"AbcKlm"
$

是的,我知道,它很丑陋,是bash函数大小的两倍,并且可以正常工作。如果可以改善:请向我们展示。

答案 2 :(得分:0)

如果需要有效的解决方案,请then带@JeffMercado的答案:

def decode_hex:
  def decode: if . < 58 then .-48 elif . < 91 then .-55 else .-87 end;
  def decode_byte: map(decode) | (.[0] * 16) + .[1];
  def pairs: explode | range(0;length;2) as $i | [.[$i], .[$i+1]];
  [pairs|decode_byte] | implode;