Bash:Oneliner将输出中的十六进制数转换为小数



有人知道可以将某些输出输送到bash中,以匹配和转换所有出现十六进制数字并将所有其他文本匹配吗?

  • 也许匹配相当任意的输出,这可能是十六进制应以某种方式转换为 /(0x)?[0-9a-fA-F]{5,}/
  • 领先的0x不得是必不可少的,但是也可以正确处理
  • 如果没有,可以有假阳性指定数字的最小长度,但这不应该是问题
  • 目标是找到可以与其中有十六进制数字的尽可能多的输出一起使用的解决方案

它应该在输出上工作:

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

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

所需的输出应该看起来像:(无论如何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的简短可行/可靠解决方案,所以我来这里寻求帮助。

使用e flag替换

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

带有autosplit Switch的perl:

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

-n开关在文件的行上提供了隐式循环。

-e开关提供可选功能,例如say Command (可用于自动运输返回的东西((。-e也做与执行参数中给出的代码的-e交换机(而不是寻找要启动的文件(。

-a开关(Autosplit(将每个线路上的每一行分开,并用零件填充@F数组(就像Awk一样(。

map { } @F处理@F的每个元素并返回新数组。

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

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

对不起。这是使用Bash的功能的单线:

cat /proc/net/stat/arp_cache | sed -e '2,$s/s*([0-9a-f][0-9a-f]*)s*/ $(( 0x1 )) /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

带有 mawk:对于每行,但第一行(NR!=1(循环从第一列到最后一列( NF(,然后将当前列($i(从十位转换为十进制。

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

输出:

条目Allocs Destroys Hash_grows查找命中res_failed rcv_probes_mcast rcv_probes_ucast ofcect occed_gc_runs forced_gc_runs unresolved_discards table_fulls13 6 4 0 49696 49605 0 0 0 38201 0 0 0 0 013 13 4 1 0 0 0 0 0 0 0 1984 0 0 0 013 8 8 1 0 0 0 0 0 0 1752 0 0 013 10 8 0 0 0 2 0 0 1775 0 0 0 0

with GNU awk

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

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

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

最新更新