在 awk 或 sed 中将十六进制转换为十进制 [英] Converting hex to decimal in awk or sed

查看:42
本文介绍了在 awk 或 sed 中将十六进制转换为十进制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数字列表,以逗号分隔:

I have a list of numbers, comma-separated:

123711184642,02,3583090366663629,639f02012437d4
123715942138,01,3538710295145500,639f02afd6c643
123711616258,02,3548370476972758,639f0200485732

我需要将第 3 列拆分为三列,如下所示:

I need to split the 3rd column into three as below:

123711184642,02,3583090366663629,639f02,0124,37d4
123715942138,01,3538710295145500,639f02,afd6,c643
123711616258,02,3548370476972758,639f02,0048,5732

并将最后两列的数字转换为十进制:

And convert the digits in the last two columns into decimal:

123711184642,02,3583090366663629,639f02,292,14292
123715942138,01,3538710295145500,639f02,45014,50755
123711616258,02,3548370476972758,639f02,72,22322

推荐答案

这是乔纳森回答的变体:

Here's a variation on Jonathan's answer:

awk $([[ $(awk --version) = GNU* ]] && echo --non-decimal-data) -F, '
    BEGIN {OFS = FS}
    {
        $6 = sprintf("%d", "0x" substr($4, 11, 4))
        $5 = sprintf("%d", "0x" substr($4,  7, 4))
        $4 = substr($4,  1, 6)
        print
    }'

我添加了一种相当扭曲的方式来添加 --non-decimal-data 选项(如果需要).

I included a rather contorted way of adding the --non-decimal-data option if it's needed.

编辑

顺便说一下,这里是纯 Bash 的等效项:

Just for the heck of it, here's the pure-Bash equivalent:

saveIFS=$IFS
IFS=,
while read -r -a line
do
    printf '%s,%s,%d,%d
' "${line[*]:0:3}" "${line[3]:0:6}" "0x${line[3]:6:4}" "0x${line[3]:10:4}"
done
IFS=$saveIFS

"${line[*]:0:3}"(引用 *)的工作方式与 AWK 的 OFS 类似,因为它导致 Bash 的 IFS(这里是逗号)被插入到输出的数组元素之间.我们可以通过如下插入数组元素来进一步利用该功能,这与我上面的 AWK 版本更接近.

The "${line[*]:0:3}" (quoted *) works similarly to AWK's OFS in that it causes Bash's IFS (here a comma) to be inserted between array elements on output. We can take further advantage of that feature by inserting array elements as follows which more closely parallels my AWK version above.

saveIFS=$IFS
IFS=,
while read -r -a line
do
    line[6]=$(printf '%d' "0x${line[3]:10:4}")
    line[5]=$(printf '%d' "0x${line[3]:6:4}")
    line[4]=$(printf '%s' "${line[3]:0:6}")
    printf '%s
' "${line[*]}"
done
IFS=$saveIFS

不幸的是,Bash 不允许 printf -v(类似于 sprintf())对数组元素进行赋值,所以 printf -v"line[6]" ... 不起作用.

Unfortunately, Bash doesn't allow printf -v (which is similar to sprintf()) to make assignments to array elements, so printf -v "line[6]" ... doesn't work.

编辑:从 Bash 4.1 开始,printf -v 现在可以对数组元素进行赋值.示例:

As of Bash 4.1, printf -v can now make assignments to array elements. Example:

printf -v 'line[6]' '%d' "0x${line[3]:10:4}"

需要在数组引用周围加上引号以防止可能的文件名匹配.如果当前目录中存在名为line6"的文件并且引用未被引用,则将创建(或更新)包含 printf 输出的名为 line6 的变量.该文件的其他任何内容(例如其内容)都不会起作用.只有名字 - 而且只是切线.

The quotes around the array reference are needed to prevent possible filename matching. If a file named "line6" existed in the current directory and the reference wasn't quoted, then a variable named line6 would be created (or updated) containing the printf output. Nothing else about the file, such as its contents, would come into play. Only the name - and only tangentially.

这篇关于在 awk 或 sed 中将十六进制转换为十进制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆