次のtcpdumpストリームがあります。
Current:
07:36:03.848461 IP 172.17.3.41.33101 > 172.17.3.43.17408: UDP, length 44
07:36:03.848463 IP 172.17.3.42.33101 > 172.17.3.43.17409: UDP, length 44
07:36:03.848467 IP SYSTEM-A.33101 > 172.17.3.43.17418: UDP, length 45
07:36:03.848467 IP SYSTEM-B.33101 > 172.17.3.43.17419: UDP, length 45
ポート番号は10進表記で表されます。ポート番号を16進数に変更した同じストリームにするには、ストリームをsedまたはawkにパイプして変更するにはどうすればよいですか?
Expected:
07:36:03.848461 IP 172.17.3.41.814d > 172.17.3.43.4400: UDP, length 44
07:36:03.848463 IP 172.17.3.42.814d > 172.17.3.43.4401: UDP, length 44
07:36:03.848467 IP SYSTEM-A.814d > 172.17.3.43.440a: UDP, length 45
07:36:03.848467 IP SYSTEM-B.814d > 172.17.3.43.440b: UDP, length 45
ポート番号がある場合は、それを使用して16進数に変換します。
echo 33101 | sed -e 's/.*://' | xargs printf "%x\n"
814d
私はこの問題を解決しようとしましたが、運がありませんでした。'.'
ストリームの3番目と5番目の列で最後に発生したポート番号を変更してからすぐに16進数に変更するにはどうすればよいですか?
答え1
そしてperl
:
perl -pe 's/\s\S+\.\K\d+/sprintf "%x", $&/ge' < your-file
\s
スペース()の後に続く単語で構成される単語を見つけます。1つ以上の順序( +
)空白ではない(\S
)、ドット、および1つ以上の数値シーケンス()を使用し、最後の部分(開始部分がと表示されます)を10進形式の同じ()に置き換えます\d+
(通常、置換はPerlコードで評価されます)。\K
$&
x
g
e
答え2
すべてのUNIXシステムのすべてのシェルでawkを使用します。
$ cat tst.awk
function mkPortHex(fldNr, port, sfx) {
port = sfx = $fldNr
sub(/.*\./,"",port)
sub(/.*[0-9]/,"",sfx)
sub(/[^.]+$/,sprintf("%x%s",port,sfx),$fldNr)
}
{
mkPortHex(3)
mkPortHex(5)
print
}
$ awk -f tst.awk file
07:36:03.848461 IP 172.17.3.41.814d > 172.17.3.43.4400: UDP, length 44
07:36:03.848463 IP 172.17.3.42.814d > 172.17.3.43.4401: UDP, length 44
07:36:03.848467 IP SYSTEM-A.814d > 172.17.3.43.440a: UDP, length 45
07:36:03.848467 IP SYSTEM-B.814d > 172.17.3.43.440b: UDP, length 45
match()の3番目の引数を一致させるには、GNU awkを使用します。
$ cat tst.awk
function mkPortHex(fldNr) {
match($fldNr,/(.*\.)([0-9]+)(:?)/,a)
$fldNr = a[1] sprintf("%x",a[2]) a[3]
}
{
mkPortHex(3)
mkPortHex(5)
print
}
$ awk -f tst.awk file
07:36:03.848461 IP 172.17.3.41.814d > 172.17.3.43.4400: UDP, length 44
07:36:03.848463 IP 172.17.3.42.814d > 172.17.3.43.4401: UDP, length 44
07:36:03.848467 IP SYSTEM-A.814d > 172.17.3.43.440a: UDP, length 45
07:36:03.848467 IP SYSTEM-B.814d > 172.17.3.43.440b: UDP, length 45
答え3
質問フィールド3と5に示すように、フィールド番号が一定の場合 - 試してみてください。
awk '
function CHX(FLD) {n = split ($FLD, T, ".")
sub (T[n] "$", sprintf ("%X", T[n]), $FLD)
}
{CHX(3)
CHX(5)
}
1
' file
07:36:03.848461 IP 172.17.3.41.814D > 172.17.3.43.4400 UDP, length 44
07:36:03.848463 IP 172.17.3.42.814D > 172.17.3.43.4401 UDP, length 44
07:36:03.848467 IP SYSTEM-A.814D > 172.17.3.43.440A UDP, length 45
07:36:03.848467 IP SYSTEM-B.814D > 172.17.3.43.440B UDP, length 45
たとえば、フィールド5の末尾のコロンは次のようになります。
awk '
function CHX(FLD) {n = split ($FLD, T, "[^0-9]")
TRM = ""
if (!T[n]) {n--
TRM = substr ($FLD, length($FLD))
}
sub (T[n] TRM "$", sprintf ("%X%s", T[n], TRM), $FLD)
}
{CHX(3)
CHX(5)
}
1
' file
答え4
答えてくれてありがとう。彼らはすべて動作します!しかし、ここでも私の解決策を投稿したいと思います。今私はこれを具体的に要求することを知っていますが、私sed
のawk
入力はtcpdump
ストリームであり、ポート番号を16進数に変更したいと思います。だからソースコードを見て、次の行を変更しました。
(void)snprintf(buf, sizeof(buf), "%u", i);
到着
(void)snprintf(buf, sizeof(buf), "%x", i); // prints hexadecimal
(void)snprintf(buf, sizeof(buf), "%u", i);
到着
(void)snprintf(buf, sizeof(buf), "%x", i); // prints hexadecimal
バイナリをコンパイルし、tcpdumpはポートを16進数で印刷します。