#linux #awk #sed
#linux #awk #sed
Вопрос:
У меня есть два файла, один называется NATLog с 3 столбцами, а другой — Sourceports с 2 столбцами, ниже приведен пример файла NATLog.
NATLog
14 172.18.2.12 445
50 172.18.24.4 123
80 10.2.123.37 22
68 172.18.1.37 25
Я хочу сопоставить последний столбец файла NATLog с первым столбцом файла Sourceports и добавить соответствующую службу в файл NATLog в качестве четвертого столбца
Исходные отчеты
445 SMB
123 Network Time Protocol (NTP)
22 SSH
25 SMTP(Insecure)
Желаемый результат
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
Я пытаюсь изучить AWK для достижения этой цели, но мне нужна некоторая помощь, не могли бы вы, пожалуйста, помочь мне, спасибо
Комментарии:
1. Я думаю, что ваш пример неуместен.
paste NATLog Sourceports
Ответ №1:
Еще один в awk (ну, на самом деле, два). Это для идеального мира:
$ awk 'NR==FNR{a[$1]=$0;next}{sub($NF,a[$NF])}1' source natlog
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
Объяснено (и немного расширено для несовершенного мира):
$ awk '
NR==FNR { # processing the source file
# gsub(/amp;/,"\\amp;") # if amp; chars in the file, uncomment to escape them
a[$1]=$0 # hash to a, port is the key
next
}
{ # process natlog file
sub($NF,a[$NF]) # replace port field with entry from source file
# sub($NF,(a[$NF]?a[$NF]:$NF)) # if gaps in source, use this instead of above
}1' source natlog
Один из возможных выходных данных (более короткий ip, amp;
символ в исходном коде и непревзойденный порт 222):
14 1.18.2.12 445 SMB amp;
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 222
68 172.18.1.37 25 SMTP(Insecure)
Ответ №2:
Попробуйте awk,
$ awk ' NR==FNR {x=$1; $1="";a[x]=$0; next } { print $0, a[$3] } ' Sourceports NATLog
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
$
Ответ №3:
awk '
NR==FNR { key=$1; sub(/[^[:space:]] [[:space:]] /,""); map[key]=$0; next }
{ print $0, map[$3] }
' Sourceports NATLog
Ответ №4:
Если вашей целью является форматирование выходных данных, отображаемое с добавлением выровненного столбца протокола, то printf
вместо print
предоставляет тот же самый мелкозернистый элемент управления форматированием, описанный в man 3 printf
(по большей части). В вашем случае вам просто нужно получить length()
значение поля номер порта и вычесть его из желаемой общей ширины поля, чтобы добавить столько пробелов после записи из NATLog
, прежде чем добавлять сохраненный протокол из Sourceports
.
Вы могли бы сделать это аналогично следующему, где в качестве примера используется общая ширина поля 4:
$ awk '
NR==FNR {pcl[$1] = $2; next} {printf "%s%*s%sn",$0,4-length($3)," ",pcl[$3]}
' Sourceports NATLog
Вывод
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
(примечание: ваш Sourceports
файл не может содержать дополнительных пробелов в конце записей. Если это произойдет, то вам придется заменить $0
на individual $1,$2,$3
и соответствующим образом настроить строку формата)
Обычно существует множество способов выполнить одно и то же в awk
, поэтому вы можете адаптировать его к любым вашим потребностям.
Используя paste
и awk
Более коротким, но менее эффективным способом было бы использовать оба paste
и awk
для достижения одной и той же цели. (в основном просто вывод первых двух полей NATLog
и добавление содержимого Sourceports
с paste
помощью, например
$ paste -d ' ' <(awk '{print $1, $2}' NATLog) Sourceports
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
(но это действительно помешало бы цели обучения awk
)
Ответ №5:
Вот почему в Linux есть куча крошечных инструментов, таких как cat
, cut
, paste
и в этом случае join
.
join -1 3 -2 1 natlog source
Объединение работает с файлами, в которых отсортирован столбец, по которому вы пытаетесь join
выполнить.
Сортировка на самом деле здесь несколько неправильная формулировка. Это должно быть больше похоже на эквивалентный порядок. Как вы заметили, оба ваших файла имеют одинаковые входные и выходные данные, и столбец, который вы пытаетесь join
использовать, эквивалентен. Так join
будет работать без проблем.
Если оба файла упорядочены неодинаково, вы могли бы использовать сортировку по нему заранее:
join -1 3 -2 1 <(sort -k3 natlog) <(sort source)
или, если вы просто хотите придерживаться одной программы, то awk
это путь вперед:
awk '(NR==FNR){k=$3; $3=""; a[k]=$0; next}{ print $0,a[$1] }' natlog source
но если natlog
и source
не имеют одинакового количества строк и / или ключей, то вы получите общую часть в виде
awk '(NR==FNR){k=$3; $3=""; a[k]=$0; next}($1 in a){ print $0,a[$1] }' natlog source
Комментарии:
1. @JamesBrown Я тебя тестировал