awk版本问题 - 将十六进制转换为十进制

时间:2011-11-10 02:43:40

标签: parsing bash sed awk

我通常在我的mac上编写脚本,然后一旦准备就绪,我就把它们放到我工作的测试盒中。我在这里遇到的问题是我有一个数据流,它是十六进制格式的I.P地址。我使用sed和awk的混合来解析它并将其转换为更易读的格式。

$echo $content12
cb5c860100000000000000000000000000 

[DoD@MBP-13~] echo $content12 | 
sed -e 's/../&./g' -e 's/.$//' | sed 's/[0-9a-z][0-9a-z]/0x&/g' | 
awk -F"." '{for (i=1;i<NF;i++) printf ("%d\n", $i)}' |
awk '{if (NR<5) printf $0; printf "."}' | sed 's/\.\.*$//'
203.92.134.1 

当我在工作时将其移植到我的测试盒时,脚本没有按预期工作。

$echo $content12 | 
sed -e 's/../&./g' -e 's/.$//' | sed 's/[0-9a-z][0-9a-z]/0x&/g' | 
awk -F"." '{for (i=1;i<NF;i++) printf ("%d\n", $i)}' | 
awk '{if (NR<5) printf $0; printf "."}' | sed 's/\.\.*$//'
0.0.0.0

我的mac上的awk和uname版本 -

[DoD@MBP-13~] awk --version
awk version 20070501

[DoD@MBP-13~] uname -a
Darwin MBP-13.local 11.2.0 Darwin Kernel Version 11.2.0: Tue Aug  9 20:54:00 PDT 2011;     
root:xnu-1699.24.8~1/RELEASE_X86_64 x86_64

我工作的测试盒上的awk和uname版本 -

$ awk --version
GNU Awk 3.1.5
Copyright (C) 1989, 1991-2005 Free Software Foundation

$uname -a
Linux 2.6.18-194.el5 #1 SMP Tue Mar 16 21:52:39 EDT 2010 
x86_64 x86_64 x86_64 GNU/Linux

这是我可以通过微小改动来解决的问题。我仍然是UNIX环境的新手,所以我的单行可能看起来异常长。任何建议将不胜感激。

3 个答案:

答案 0 :(得分:3)

您可以使用--non-decimal-data的{​​{1}}选项使其处理输入中的八进制和十六进制数字:

gawk

$ echo 0x10 | gawk --non-decimal-data '{ printf "%d", $1 }'
16

答案 1 :(得分:1)

从本质上讲,这个问题归结为向printf提供一串参数。printf是一个内置的shell:

echo "cb5c860100000000000000000000000000" |
sed 's/\(.\{8\}\).*/\1/;s/../"0x&" /g;s/^/printf "%d.%d.%d.%d\n" /'|sh
203.92.134.1

在GNU sed中,您可以评估模式空间,如下所示:

echo "cb5c860100000000000000000000000000" |
sed 's/\(.\{8\}\).*/\1/;s/../"0x&" /g;s/^/printf "%d.%d.%d.%d" /e'
203.92.134.1

在编程中,我发现最困难的事情不是编码而是说出你的意思。

答案 2 :(得分:0)

显然,当你实现它时,GNU awk(1)实现不会将0x11作为printf()的参数处理:

$ echo cb5c860100000000000000000000000000 | sed -e 's/../&./g' -e 's/.$//' |
  sed 's/[0-9a-z][0-9a-z]/0x&/g'
0xcb.0x5c.0x86.0x01.0x00.0x00.0x00.0x00.0x00.0x00.0x00.0x00.0x00.0x00.0x00.0x00.0x00
$ echo cb5c860100000000000000000000000000 | sed -e 's/../&./g' -e 's/.$//' |
  sed 's/[0-9a-z][0-9a-z]/0x&/g' |
  awk -F"." '{for (i=1;i<NF;i++) printf ("%d\n", $i)}'
0
0
0
...

我的系统上安装的mawk(1)(由Mike Brennan提供) - GNU awk(1)的替代方案,声称更小,更快,并且仍然符合POSIX 1003.2(草案11.3) - 按预期解释这个:

$ echo cb5c860100000000000000000000000000 | sed -e 's/../&./g' -e 's/.$//' |
  sed 's/[0-9a-z][0-9a-z]/0x&/g' |
  mawk -F"." '{for (i=1;i<NF;i++) printf ("%d\n", $i)}' |
  mawk '{if (NR<5) printf $0; printf "."}' | sed 's/\.\.*$//'
203.92.134.1$ 

如果您足够幸运也可以安装mawk(1),则此解决方案可能适用。