在awk或sed中将十六进制转换为十进制

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

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

我需要将第3列分为以下三个:

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

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

123711184642,02,3583090366663629,639f02,292,14292
123715942138,01,3538710295145500,639f02,45014,50755
123711616258,02,3548370476972758,639f02,72,22322
最佳答案
乔纳森的回答是一个变化:

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选项.

编辑

只是为了这一点,这里是纯Bash的等价物:

saveIFS=$IFS
IFS=,
while read -r -a line
do
    printf '%s,%s,%d,%d\n' "${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版本更接近.

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\n' "${line[*]}"
done
IFS=$saveIFS

不幸的是,Bash不允许printf -v(类似于sprintf())来对数组元素进行赋值,因此printf -v“line [6]”…不起作用.

转载注明原文:在awk或sed中将十六进制转换为十进制 - 代码日志