パイプを介して最初のフィールドを10進数から16進数に変換する方法

パイプを介して最初のフィールドを10進数から16進数に変換する方法

次の画面出力があります。

170.170.170.0.156.96 24

パイプして次の形式に変換したい

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

デフォルトでは、最初のフィールドは10進数から16進数に変換され、点はコロンで置き換えられます。どんな提案がありますか?

答え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])を削除し、すべての数字を対応する16進数と.to:tr変換に置き換えます。 printに含まれる新しい値@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使用して10進数を16進数に変換することによって生成されますsprintf()。入力が完了したら結果を印刷します。

10進数から16進数への変換では末尾が24削除されるため、明示的に処理する必要はありません。

上記のパイプの結果は文字列ですaa:aa:aa:00:9c:60

答え4

IFSIPアドレス部分を処理するには、サブシェルのトークン化(引用符なし$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

後でスクリプトからの出力も必要な場合は、結果の値を名前付きパイプに書き込む、同じサブシェルで作業を続ける、またはプロセス置換を使用することを検討してください。バラよりこれより多くの情報を知りたいです。

関連情報