Объединение двух списков файлов на основе уникального столбца

В вашем вопросе отмечен C ++, и есть хорошие способы (например, потоки), чтобы полностью исключить varargs на C ++.

Это отличный пример того, почему va_args может вызвать боль. Если у вас есть шанс изменить подпись foo, это ваш лучший вариант. Взяв std::vector<std::string> вместо va_list, вы просто решите свою проблему там.

Если foo находится во внешней библиотеке, которую вы не можете изменить, моим следующим предложением было бы найти другую библиотеку.

Если ни один из них не является вариантом, кажется, что должен быть способ рекурсивно создать список вызовов с помощью va_list, но я не мог понять, как это сделать.

0
задан jww 11 March 2019 в 22:01
поделиться

5 ответов

awk '
    NR==FNR { key=$1; sub(/[^[:space:]]+[[:space:]]+/,""); map[key]=[110]; next }
    { print [110], map[$3] }
' Sourceports NATLog
0
ответ дан Ed Morton 11 March 2019 в 22:01
поделиться

Еще один в awk (ну, два на самом деле). Это для идеального мира:

$ awk 'NR==FNR{a[$1]=[110];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]=[111]                       # 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, & char в источнике и непревзойденный порт 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)
0
ответ дан James Brown 11 March 2019 в 22:01
поделиться

Попробуйте awk,

$ awk ' NR==FNR {x=$1; $1="";a[x]=[110]; next } { print [110], 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
ответ дан stack0114106 11 March 2019 в 22:01
поделиться

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

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

$ awk '
    NR==FNR {pcl[$1] = $2; next} {printf "%s%*s%s\n",[110],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 не может содержать дополнительные пробелы в конце записей. Если это произойдет, вам придется заменить [1110] на отдельный $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) [ 1129]

0
ответ дан David C. Rankin 11 March 2019 в 22:01
поделиться

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

join -1 3 -2 1 natlog source

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

1117 Сортировка - на самом деле несколько неправильная формулировка. Это должно быть больше похоже на эквивалентно упорядоченный . Как вы заметили, оба ваших файла имеют одинаковый ввод и вывод, и столбец, к которому вы пытаетесь join, эквивалентен. Так что join будет работать без проблем.

Если оба файла упорядочены по-разному, вы можете использовать сортировку по нему заранее:

join -1 3 -2 1 <(sort -k3 natlog) <(sort source)

или если вы просто хотите придерживаться одной программы, тогда awk - путь вперед: 1119]

awk '(NR==FNR){k=$3; $3=""; a[k]=[112]; next}{ print [112],a[$1] }' natlog source

, но если natlog и source не имеют одинаковое количество линий и / или ключей, то вы получите общую часть как

awk '(NR==FNR){k=$3; $3=""; a[k]=[113]; next}($1 in a){ print [113],a[$1] }' natlog source
0
ответ дан kvantour 11 March 2019 в 22:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: