如何 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
我需要统计日志文件中每小时的消息数。每个日志文件行前面都有时间戳。因此,我使用以下 '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