Bash: 格式化 multi-line 函数结果并排排列
Bash: Formatting multi-line function results alongside each other
我有三个函数可以消化我服务器上的 access.log
文件。
hitsbyip() {
cat $ACCESSLOG | awk '{ print }' | uniq -c | sort -nk1 | uniq
}
hitsbyhour() {
cat $ACCESSLOG | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print ":00"}' | sort -n | uniq -c
}
hitsbymin() {
hr=
grep "2015:${hr}" $ACCESSLOG | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print ":"}' | sort -nk1 -nk2 | uniq -c
}
它们单独使用时都能正常工作。三个都输出 2 小列数据。
现在我想创建另一个名为 report
的函数,它将简单地使用 printf
及其格式化可能性来打印具有 header 的 3 列数据,每列结果我的前三个功能。类似的东西:
report() {
printf "%-30b %-30b %-30b\n" `hitsbyip` `hitsbyhour` `hitsbymin 10`
}
问题是格式不是我想要的;它水平打印出列,而不是并排打印。
如有任何帮助,我们将不胜感激。
一旦您使用 paste
将三个命令的输出合并为一个流,然后 您可以逐行操作来格式化这些输出。
while IFS=$'\t' read -r by_ip by_hour by_min; do
printf '%-30b %-30b %-30b\n' "$by_ip" "$by_hour" "$by_min"
done < <(paste <(hitsbyip) <(hitsbyhour) <(hitsbymin 10))
注意事项:
<()
语法为process substitution;它生成一个文件名(在具有此类支持的平台上通常为 /dev/fd/##
形式),读取时将产生给定命令的输出。
paste
获取一系列文件名并将每个文件名的输出放在一起。
- 在阅读时设置
IFS=$'\t'
可确保我们以制表符分隔值(paste
创建的格式)读取内容。有关使用 read
. 的详细信息,请参阅 BashFAQ #1
- 在
printf
的参数上加上引号确保我们将 read
组装的每个值作为单个值传递给 printf
,而不是让它们受到字符串拆分的影响和全局扩展作为未引用的值。
我有三个函数可以消化我服务器上的 access.log
文件。
hitsbyip() {
cat $ACCESSLOG | awk '{ print }' | uniq -c | sort -nk1 | uniq
}
hitsbyhour() {
cat $ACCESSLOG | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print ":00"}' | sort -n | uniq -c
}
hitsbymin() {
hr=
grep "2015:${hr}" $ACCESSLOG | cut -d[ -f2 | cut -d] -f1 | awk -F: '{print ":"}' | sort -nk1 -nk2 | uniq -c
}
它们单独使用时都能正常工作。三个都输出 2 小列数据。
现在我想创建另一个名为 report
的函数,它将简单地使用 printf
及其格式化可能性来打印具有 header 的 3 列数据,每列结果我的前三个功能。类似的东西:
report() {
printf "%-30b %-30b %-30b\n" `hitsbyip` `hitsbyhour` `hitsbymin 10`
}
问题是格式不是我想要的;它水平打印出列,而不是并排打印。
如有任何帮助,我们将不胜感激。
一旦您使用 paste
将三个命令的输出合并为一个流,然后 您可以逐行操作来格式化这些输出。
while IFS=$'\t' read -r by_ip by_hour by_min; do
printf '%-30b %-30b %-30b\n' "$by_ip" "$by_hour" "$by_min"
done < <(paste <(hitsbyip) <(hitsbyhour) <(hitsbymin 10))
注意事项:
<()
语法为process substitution;它生成一个文件名(在具有此类支持的平台上通常为/dev/fd/##
形式),读取时将产生给定命令的输出。paste
获取一系列文件名并将每个文件名的输出放在一起。- 在阅读时设置
IFS=$'\t'
可确保我们以制表符分隔值(paste
创建的格式)读取内容。有关使用read
. 的详细信息,请参阅 BashFAQ #1
- 在
printf
的参数上加上引号确保我们将read
组装的每个值作为单个值传递给printf
,而不是让它们受到字符串拆分的影响和全局扩展作为未引用的值。