bash:将输出中的十六进制数转换为十进制数的单行代码

bash: oneliner to convert hex numbers in output to decimals

有谁知道可以将一些输出输入 bash 的 oneliner,以匹配和转换所有出现的十六进制数并保持所有其他文本不变?

它应该像这样输出:

ssg sjas # cat /proc/net/stat/arp_cache | column -t 
entries   allocs    destroys  hash_grows  lookups   hits      res_failed  rcv_probes_mcast  rcv_probes_ucast  periodic_gc_runs  forced_gc_runs  unresolved_discards  table_fulls
0000000d  00000006  00000004  00000000    0000c3b9  0000c35e  00000000    00000000          00000000          0000965b          00000000        00000000             00000000
0000000d  0000000d  00000004  00000001    00000000  00000000  00000000    00000000          00000000          000007cd          00000000        00000000             00000000
0000000d  00000008  00000008  00000001    00000000  00000000  00000000    00000000          00000000          000006e0          00000000        00000000             00000000
0000000d  0000000a  00000008  00000000    00000000  00000000  00000002    00000000          00000000          00000704          00000000        00000000             00000000

Whosebug 上的大多数其他问题只解决如何在数字系统之间转换单个数字的问题,只对指定列进行转换或完全取消输入中存在的格式。

期望的输出应该是这样的:(column -t 无论如何,它真的只需要替换它能找到的十六进制值,并且在 printf 语句中添加前导零也不是问题)

ssg sjas # cat /proc/net/stat/arp_cache | perl -pe 's/(?:0x)?[0-9a-f]{5,}/hex($&)/ge' | column -t
entries  allocs  destroys  hash_grows  lookups  hits   res_failed  rcv_probes_mcast  rcv_probes_ucast  periodic_gc_runs  forced_gc_runs  unresolved_discards  table_fulls
13       6       4         0           50105    50014  0           0                 0                 38491             0               0                    0
13       13      4         1           0        0      0           0                 0                 1997              0               0                    0
13       8       8         1           0        0      0           0                 0                 1760              0               0                    0
13       10      8         0           0        0      2           0                 0                 1796              0               0                    0

最近两个小时没能通过sed/awk/perl找到简短的viable/reliable解决方案,所以才来这里求助

前导 0 被认为是八进制,前导 0x 被认为是十六进制。如果您的数字符合该标准,那么 $(( <number> )) 会将它们转换为十进制:

$ echo $(( 0x1b ))
27
$ echo $(( 014 ))
12

GNU awk:

awk 'BEGIN{IFS=OFS="\t"}NR==1{print [=10=]}{for(i=1;i<=NF;i++) if(i!=NF){printf "%s%c",strtonum("0x"$i),OFS}else{printf "%d\n",strtonum("0x"$i)}}' filename

带有自动拆分开关的 perl:

perl -anE'say join " ", map {/(?:0x)?([0-9a-f]{5,})/i ? hex  : $_} @F' file | column -t

-n 开关提供对文件行的隐式循环。

-E 开关使可选功能可用,例如 say 命令 (用于打印带有自动回车的内容 return)。 -E 也执行与执行参数中给定代码的 -e 开关相同的事情(而不是查找要启动的文件)。

-a 开关(自动拆分)在空白处拆分每一行,并用这些部分填充 @F 数组(就像 awk 所做的那样)。

map { } @F 处理 @F 和 return 的每个元素一个新数组。

/(?:0x)?([0-9a-f]{5,})/i ? hex() : $_ 使用三元运算符 condition ? true : false。当模式与它匹配时 return 转换后的捕获组 1,当它不匹配原始部分时。

请注意,Perl 是一种考虑上下文的​​语言。 map {} 中的 $_ 指的是 @F 项,/(?:0x)?([0-9a-f]{5,})/i$_ =~ /(?:0x)?([0-9a-f]{5,})/i 的缩写。 map {} $_ 之外是当前行)

perl 使用 e 标志进行替换

perl -pe 's/(0x)?[0-9a-f]{5,}/hex $&/ge' file | column -t

With mawk:除了第一行之外的每一行 (NR!=1) 从第一列循环到最后一列 (NF) 并将当前列 ($i) 从十六进制转十进制。

mawk 'NR!=1 {for (i=1; i<=NF; i++) $i=sprintf("%d ","0x"$i)}1' file | column -t

输出:

entries  allocs  destroys  hash_grows  lookups  hits   res_failed  rcv_probes_mcast  rcv_probes_ucast  periodic_gc_runs  forced_gc_runs  unresolved_discards  table_fulls
13       6       4         0           49696    49605  0           0                 0                 38201             0               0                    0
13       13      4         1           0        0      0           0                 0                 1984              0               0                    0
13       8       8         1           0        0      0           0                 0                 1752              0               0                    0
13       10      8         0           0        0      2           0                 0                 1775              0               0                    0

抱歉造成混淆。这是一个使用 bash:

特性的单行代码
cat /proc/net/stat/arp_cache | sed -e '2,$s/\s*\([0-9a-f][0-9a-f]*\)\s*/ $\(\( 0x \)\) /g' -e 's/^/echo /' | bash | column -t
entries  allocs  destroys  hash_grows  lookups  hits  res_failed  rcv_probes_mcast  rcv_probes_ucast  periodic_gc_runs  forced_gc_runs  unresolved_discards  table_fulls
8        2       0         0           0        0     0           0                 0                 0                 0               0                    0
8        0       0         0           211      58    0           0                 0                 0                 0               0                    0
8        2       0         0           6319     1677  0           0                 0                 3882              0               0                    0
8        4       0         0           4731     1299  0           0                 0                 0                 0               0                    0