Объединение двух списков файлов на основе уникального столбца - PullRequest
0 голосов
/ 11 марта 2019

У меня есть два файла, один называется 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 в качестве 4-го столбца

Sourceports

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 для достижения этой цели, но мне нужна помощь, не могли бы вы помочь мне,спасибо

Ответы [ 5 ]

3 голосов
/ 12 марта 2019

Еще один в 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(/&/,"\\\\&")              # if & 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, & символ в источнике и непревзойденный порт 222):

14 1.18.2.12   445 SMB & 
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 222
68 172.18.1.37 25  SMTP(Insecure)
1 голос
/ 12 марта 2019
awk '
    NR==FNR { key=$1; sub(/[^[:space:]]+[[:space:]]+/,""); map[key]=$0; next }
    { print $0, map[$3] }
' Sourceports NATLog
1 голос
/ 12 марта 2019

Если вашей целью является вывод форматирования , показанного с добавленным выравниваемым столбцом протокола, тогда printf вместо print обеспечивает тот же самый мелкозернистый элемент управления форматированием, как описано в man 3 printf (по большей части).В вашем случае вам просто нужно получить length() поля номера порта и вычесть его из желаемой общей ширины поля, чтобы добавить столько пробелов после записи из NATLog перед добавлением сохраненного протокола из Sourceports.

Это можно сделать аналогично следующему, если в качестве примера используется общая ширина поля 4:

$ awk '
    NR==FNR {pcl[$1] = $2; next} {printf "%s%*s%s\n",$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 на отдельный $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)

1 голос
/ 11 марта 2019

Попробуйте 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)

$
0 голосов
/ 12 марта 2019

Именно поэтому в linux есть куча крошечных инструментов, таких как cat, cut, paste, и в этом случае join.

join -1 3 -2 1 natlog source

Объединение работает с файлами, в которых столбецвы пытаетесь join on отсортировано.

Sorted на самом деле является несколько неправильной формулировкой.Это должно быть больше похоже на эквивалентно упорядоченный .Как вы заметили, оба ваших файла имеют одинаковые входные и выходные данные, и столбец, к которому вы пытаетесь подключить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...