bash:将输出中的十六进制数转换为十进制数的单行代码
bash: oneliner to convert hex numbers in output to decimals
有谁知道可以将一些输出输入 bash
的 oneliner,以匹配和转换所有出现的十六进制数并保持所有其他文本不变?
- 可能匹配相当任意的十六进制输出
应以某种方式通过正则表达式转换,即
/(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
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
有谁知道可以将一些输出输入 bash
的 oneliner,以匹配和转换所有出现的十六进制数并保持所有其他文本不变?
- 可能匹配相当任意的十六进制输出
应以某种方式通过正则表达式转换,即
/(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
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