В вашем вопросе отмечен C ++, и есть хорошие способы (например, потоки), чтобы полностью исключить varargs на C ++.
Это отличный пример того, почему va_args может вызвать боль. Если у вас есть шанс изменить подпись foo
, это ваш лучший вариант. Взяв std::vector<std::string>
вместо va_list, вы просто решите свою проблему там.
Если foo
находится во внешней библиотеке, которую вы не можете изменить, моим следующим предложением было бы найти другую библиотеку.
Если ни один из них не является вариантом, кажется, что должен быть способ рекурсивно создать список вызовов с помощью va_list, но я не мог понять, как это сделать.
awk '
NR==FNR { key=$1; sub(/[^[:space:]]+[[:space:]]+/,""); map[key]=[110]; next }
{ print [110], map[$3] }
' Sourceports NATLog
Еще один в 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)
Попробуйте 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)
$
Если вашей целью является выходное форматирование , показанное с выровненным столбцом протокола, тогда 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]
Именно поэтому в 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
- путь вперед: 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