如何grep以数字或空格开头的行

时间:2015-02-09 20:54:32

标签: regex bash grep

我需要在日志文件中计算每小时的消息数。每个日志文件行前面都有时间戳。因此我使用'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一个数字前面只有一个空格或一行的开头。

4 个答案:

答案 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