如何通过管道将第一个字段从十进制转换为十六进制

如何通过管道将第一个字段从十进制转换为十六进制

我有以下屏幕输出

170.170.170.0.156.96 24

我想通过管道传输并转换为以下格式

b8:27:eb:ef:3b:4a 24

本质上,它是第一个字段的十进制到十六进制的转换,其中点被冒号替换。有什么建议么?

答案1

$ cat input
170.170.170.0.156.96 24
$ perl -lane '$F[0] =~ s/(\d+)/sprintf "%02x",$1/eg; $F[0] =~ tr/./:/; print "@F"' < input
aa:aa:aa:00:9c:60 24
$ 

循环遍历标准输入而不打印,并拆分为@F,破坏第一列 ( $F[0]) 将所有数字替换为其十六进制等效值加上 .至:tr翻译。打印 中包含的新值@F

答案2

Python方法:

-- 使用re模块:

python -c 'import sys,re;
print(re.sub(r"\d+(?!$)", lambda m: "{:x}".format(int(m.group())), 
sys.stdin.read().strip()))' <inputfile

-- 使用split()++map()join()

python -c 'import sys; parts=sys.stdin.read().strip().split(); 
print(".".join(map(lambda n: "{:x}".format(int(n)), parts[0].split("."))) 
 + " " + parts[1])' <inputfile

输出(两种方法):

aa.aa.aa.0.9c.60 24

答案3

使用awk和处理点作为记录分隔符:

echo '170.170.170.0.156.96 24' |
awk -v RS='.' '{ s = (s ? s ":" : "" ) sprintf("%02x", $0) } END { print s }'

在这里,结果字符串s是通过使用 将十进制整数转换为十六进制而构建的sprintf()。输入结束后,打印结果。

请注意,尾随24在十进制到十六进制转换中被丢弃,因此不需要对其进行显式处理。

上述管道的结果是字符串aa:aa:aa:00:9c:60

答案4

为了处理 IP 地址部分,我们可以利用IFSsubshel​​l 中的分词(因此不带引号$var)以及printf处理可变长度参数以适应格式字符串的能力。

$ ( IFS='.';var='170.170.170.0.156.96';new=$(printf '%02x:' $var); echo ${new:0:${#new}-1} )
aa:aa:aa:00:9c:60

还值得注意的是, ${new:0:${#new}-1}用于修剪:盲目添加的最后一个字符printf

考虑到 可能170.170.170.0.156.96 24作为单个输入字符串出现stdin,我们可以将它们都读入变量并分别处理:

$ echo "170.170.170.0.156.96 24" | while read ip num ;  do
> hex=$( IFS='.';new=$(printf '%02x:' $ip); echo ${new:0:${#new}-1} );  
> printf '%s %d\n' "$hex" "$num"; done
aa:aa:aa:00:9c:60 24

如果您还需要稍后在脚本中使用输出,请考虑将结果值写入命名管道、继续在同一子 shell 中工作或使用进程替换。看了解更多信息。

相关内容