2011-11-10 98 views
2

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

$echo $content12 
cb5c860100000000000000000000000000 

[[email protected]~] 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 

版本的awk和UNAME我的Mac上 -

[[email protected]~] awk --version 
awk version 20070501 

[[email protected]~] 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

您可以使用gawk--non-decimal-data选项,使其在输入处理八进制和十六进制数:

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

与:

$ echo 0x10 | gawk '{ printf "%d", $1 }' 
0 
+0

工程很棒。万分感谢! –

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)安装在我的系统(由麦克·布伦南)上 - 以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)安装和使用,这种解决方案可能是合适的。

+0

谢谢sarnold。不幸的是,我没有安装在我的测试盒上。我将不得不使用系统管理员来部署它。我已经使用@Rick的答案,因为它很容易实现。 –

+0

我也喜欢@里克的回答,它比我的破坏性要小得多。当我看到他的回答时,我正在忙着阅读'gawk(1)'手册页,试图找出如何使用'CONVFMT',所以我放弃了。 :) – sarnold

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 

在编程中,我发现最难的不是编码,但说什么你意思是。

+0

感谢波通..这看起来很酷。 +1 –