我正在使用以下语句审核我的access_logs:
cat access_log | grep 16/Sep/2012:17 | awk '{print $12 $13 $14 $15 $16}' | sort | uniq -c | sort -n | tail -40
目的是查看按命中数排序的最后一小时内按照我的服务器命名的任何人的用户代理。我的服务器有不寻常的活动,我想要阻止任何不需要的蜘蛛/等。
但是部分:awk '{print $12 $13 $14 $15 $16}'
会更像是awk '{print $12-through-end-of-line}'
,因此我可以看到每个用户代理的长度不同。
有没有办法用awk做到这一点?
答案 0 :(得分:2)
不是很优雅,但这有效:
grep 16/Sep/2012:17 access_log | awk '{for (i=12;i<=NF;++i) printf "%s ",$i;print ""}'
它的副作用是将字段之间的多个空格缩小到一个,然后在行的末尾添加一个额外的空格,这可能并不重要。
答案 1 :(得分:2)
我从未找到过;在这种情况下,我使用cut
(假设我不需要awk
灵活处理字段分离):
# Assuming tab-separated fields, cut's default
grep 16/Sep/2012:17 access_log | cut -f12- | sort | uniq -c | sort -n | tail -40
# For space-separated fields (single spaces, not arbitrary amounts of whitespace)
grep 16/Sep/2012:17 access_log | cut -d' ' -f12- | sort | uniq -c | sort -n | tail -40
(澄清:我从来没有找到好的方式。我在必要时使用了@ twalberg的for循环,但如果可能的话,更喜欢使用cut
。)
答案 2 :(得分:1)
$ echo somefields:; cat somefields ; echo from-to.awk: ; \
cat from-to.awk ; echo ;awk -f from-to.awk somefields
somefields:
a b c d e f g h i j k l m n o p q r s t u v w x y z
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
from-to.awk:
{ for (i=12; i<=NF; i++) { printf "%s ", $i }; print "" }
l m n o p q r s t u v w x y z
12 13 14 15 16 17 18 19 20 21
来自man awk:
NF当前输入记录中的字段数。
所以你基本上将字段(用空格分隔)从12循环到最后一个。
答案 3 :(得分:0)
为什么不
#!/bin/bash
awk "/$1/"'{for (i=12;i<=NF;i++) printf("%s ", $i) ;printf "\n"}' log | sort | uniq -c | sort -n | tail -40
在脚本文件中。
然后您可以将其称为
myMonitor.sh 16/Sep/2012:17
没有办法测试这个权利。适用于任何格式/语法错误的应用程序。 希望你明白了。
IHTH
答案 4 :(得分:0)
awk '/16/Sep/2012:17/{for(i=1;i<12;i++){$i="";}print}' access_log| sort | uniq -c | sort -n | tail -40