我需要在日志文件中计算每小时的消息数。每个日志文件行前面都有时间戳。因此我使用'for'和'grep'命令来执行此操作 -
for i in `seq 0 23`
do egrep "$i:[0-9][0-9]:[0-9][0-9] <some_pattern>" filename | wc -l
done
这将为我提供每小时0到23的消息数。
然而,这不适用于单个数字小时,例如5:23:32
,因为它前面有一个空格。然后grep必须是 -
egrep " $i:[0-9][0-9]:[0-9][0-9] <some_pattern>" filename | wc -l
如果不匹配则会错误地匹配以15:23:32
那么我怎么能告诉grep一个数字前面只有一个空格或一行的开头。
答案 0 :(得分:1)
我想我可以摆脱你的for
循环。如果该时间(而不是日期)开始每一行,这将有效:
$ awk -F : '/some_pattern/ { print $1 }' file |sort |uniq -c
这将搜索您想要的模式(类似于grep
),然后打印第一个元素(由冒号分隔),这将是小时。然后对其进行排序,并计算重复的独特元素并显示在标准输出上。
但是,假设您的日志看起来像/var/log/syslog
,其行如下所示:
Feb 9 01:23:45 mycomputer service[PID]: details...
在这种情况下,你必须告诉AWK在哪里看:
$ awk '/some_pattern/ { gsub(/:.*/,"",$3); print $3 }' file |sort |uniq -c
这将搜索您想要的模式(类似grep
),然后在第三个元素的第一个冒号(时间)之后替换所有剩余的(小时)。其余的如上所述。
示例输出(以上任一变体):
12 07
34 08
30 09
51 10
536 11
346 12
123 13
这注意到早上7点我的查询有12个匹配,直到上午11点才开始使用这个系统。
答案 1 :(得分:1)
使用egrep
for i in `seq 0 23`; do egrep -c "^[[:space:]]*$i:[0-9][0-9]:[0-9][0-9] <some_pattern>" 'filename'; done
^[[:space:]]*$i:[0-9][0-9]:[0-9][0-9]
这将告诉egrep从行首开始匹配。如果该行以行开头的空格开头,或者只是以您的模式开头,则grep将匹配它。这也会告诉grep匹配不要贪婪地匹配。
例如
使用带有模式的命令查找5:23:32
,(其中$ i = 5)我们得到
5:23:23
15:23:23
使用上面的命令,我们得到
5:23:23
grep附带一个-c选项来计算
你也可以使用grep的-c选项而不是管道到wc -l
例如
for i in `seq 0 23`; do egrep -c "^[[:space:]]*$i:[0-9][0-9]:[0-9][0-9] <pattern>" 'filename'; done
答案 2 :(得分:0)
grep "^[ 0-9][0]9...
我认为这是你正在寻找的,除非我误解了你的问题。将空格添加到第一个集合作为选项,并将其锚定到行的开头。
答案 3 :(得分:0)
要匹配从0到9的小时是空格填充或零填充的时间戳:
使用基本正则表达式
grep '^\([ 01][0-9]\|2[0-3]\):[0-5][0-9]:[0-5][0-9]' file
或扩展正则表达式
grep -E '^([ 01][0-9]|2[0-3])(:[0-5][0-9]){2}' file
参考:https://www.gnu.org/software/gnulib/manual/html_node/Regular-expression-syntaxes.html