У меня было такое же сообщение об ошибке. Я решил это, используя следующее в командной строке:
xfreerdp /sec:rdp /u:fake.user /v:fake.host.com
Если номера полей постоянны -, как в полях 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
Сperl
:
perl -pe 's/\s\S+\.\K\d+/sprintf "%x", $&/ge' < your-file
Ищет слова, состоящие из пробела (\s
), за которым следует последовательность из одного или нескольких(+
)не -пробелов (\S
), точка и последовательность из одной или нескольких цифр(\d+
)и заменяет конечную часть (, начало которой помечено как \K
), на тот же ($&
), отформатированный в x
десятичном(g
глобально, замена e
оценивается как perl-код ).
С любым awk в любой оболочке на каждой машине UNIX:
$ 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
С GNU awk для соответствия 3-го аргумента():
$ 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
Спасибо всем за ответы! Все работают! Однако я хотел бы опубликовать свое решение и здесь. Теперь я знаю, что я специально просил sed
и awk
для этого, но мой ввод представляет собой поток tcpdump
, и я хотел изменить номера портов на шестнадцатеричные. Поэтому я просмотрел исходный код и изменил следующие строки:
(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 выводит порты в шестнадцатеричном формате.
Сначала следует спросить, разумно ли это, имея 172.17.3.43.440a
, где первые 4 поля, разделенные точками, являются десятичными, а 5-е — шестнадцатеричным, выглядит странно. Однако давайте предположим, что у ОП есть веские причины.
ОП предоставил нам некоторые образцы данных и желаемый результат, это очень полезно.
ОП показывает нам echo 33101 | sed -e 's/.*://' | xargs printf "%x\n"
, что дает нам некоторое представление об их мыслительных процессах. Это говорит мне, что они на ложном пути. Они хотят как-то разбить строку (с помощью awk
или sed
на основе тегов ), с помощью printf
преобразовать ее в шестнадцатеричный формат, а затем снова собрать линию. Повторите для каждой строки. Хотя очевидно, что это можно заставить работать, это очень медленно. Процессы Unix и Linux дешевы, но не бесплатны. Этот подход будет использовать много процессов на строку, и можно ожидать, что вывод потока tcpdump будет состоять из многих сотен строк. Желательно выполнять изменение, используя только несколько процессов на файл , чтобы это имело разумную скорость, если это вообще возможно.
Итак, о выборе инструмента. Теги предполагают sed
и awk
. Я бы отверг sed
. Онturing complete
(предполагает бесконечный объем памяти )и поэтому может делать все, что можно сделать на любом другом языке, но это не значит, что он будет легким или читабельным. Если бы я делал это, я, вероятно, потянулся бы к perl
или python
, но awk
вполне разумно, так что давайте воспользуемся этим.
awk
программы перебирают строки сами по себе, так что это хорошее начало. ОП говорит о third column
, но, глядя на желаемый результат, они также хотят и пятый. Они не хотят, чтобы миллисекунды в первом столбце преобразовывались в шестнадцатеричный формат, хотя это тоже число after last occurrence of '.'
. Так что есть выбор, который нужно сделать,мы перебираем каждый из столбцов (, называемых «полями» в awk )после первого, или мы просто делаем третий и пятый? Либо будет работать. Возьмем общий случай и сделаем все столбцы. Это дает нам
for(f=2;f<NF;f++){
# do something with field f
}
Теперь нам нужно посмотреть, соответствует ли поле .
, за которым следует число, а затем необязательный :
(, поэтому мы преобразуем 5-е поле в исходные данные ). Это можно сделать с помощью регулярных выражений, одной из мощных идей, популяризированных Unix.
for(f=2;f<NF;f++){
if ($f ~ /\.[0-9][0-9]*:?$/) {
# this field needs to be converted
}
}
Теперь займемся преобразованием. Используйте match
, чтобы разбить шаблон, и sprintf, чтобы вернуть его, чтобы получить окончательную программу
#!/usr/bin/awk -f
{
for(f=2;f<NF;f++){
if ($f ~ /\.[0-9][0-9]*:?$/) {
match($f,/^(.*\.)([0-9][0-9]*)(:?)$/,a)
$f=sprintf("%s%x%s",a[1],a[2],a[3])
}
}
print
}