我有以下屏幕输出
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 地址部分,我们可以利用IFS
subshell 中的分词(因此不带引号$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 中工作或使用进程替换。看这了解更多信息。