在 awk 或 sed 中将十六进制转换为十进制 [英] Converting hex to decimal in awk or 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屋!