如何 grep 以数字或白色开头的行 space

How to grep lines starting with a digit or white space

我需要统计日志文件中每小时的消息数。每个日志文件行前面都有时间戳。因此,我使用以下 '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 等个位数的小时,因为它前面有一个白色的 space。然后 grep 必须是 -

egrep " $i:[0-9][0-9]:[0-9][0-9] <some_pattern>" filename | wc -l

如果不是,它将错误地匹配以 say 15:23:32

开头的行

那么我如何告诉 grep 一个数字前面可以有一个 space 或行的开头。

grep "^[ 0-9][0]9...

我认为这就是您要查找的内容,除非我误解了您的问题。将空格作为选项添加到第一组并将其固定到行的开头。

我想我可以摆脱你的 for 循环。如果那个时间(而不是日期)开始每一行,这将起作用:

$ awk -F : '/some_pattern/ { print  }' file |sort |uniq -c

这将搜索您想要的模式(有点像 grep),然后打印第一个元素(由冒号分隔),即小时。然后对其进行排序,并对唯一元素的重复进行计数并显示在标准输出上。

但是,假设您的日志看起来像 /var/log/syslog,其中的行如下所示:

Feb  9 01:23:45 mycomputer service[PID]: details...

在这种情况下,您必须告诉 AWK 在哪里查找:

$ awk '/some_pattern/ { gsub(/:.*/,"",); print  }' file |sort |uniq -c

这将搜索您想要的模式(有点像 grep),然后替换第三个元素(时间)的第一个冒号之后的所有内容,并打印剩余的内容(小时)。其余如上所述。

示例输出(上述任一变体):

 12 07
 34 08
 30 09
 51 10
536 11
346 12
123 13

这表明我在早上 7 点有 12 个匹配项,直到上午 11 点我才真正开始使用这个系统。

要匹配从 0 到 9 的小时是 space 填充或零填充的时间戳:

有基本的正则表达式

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

使用 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