awk '/10:..:/, /13:..:/' server.log > /tmp/awktmp
我按照有人给我的命令尝试了这个命令。它对我来说可以找到上午 10:00 到下午 13:00 之间的日志,但我不完全理解它。
如果您有一个优雅的解决方案,请告诉我。请记住,远程服务器很小,并且没有高级实用程序。
我在这里不明白的是'/10:..:/, /13:..:/'
- 我理解
10:..
意思是10
和:
完全匹配 2 位数字。 - 但另一个是什么
:
意思呢?
我想正斜杠是用来放置正则表达式的,就像我们在 JavaScript 正则表达式中所做的那样。我对此不是100%确定。
更新1:
时间位于第二列,格式为HH:MM:SS
更新2:
sed -n -e '/8:..:../,/9:..:../p' application.log > /tmp/sedtmp
我尝试了这个,但这也显示了来自 的日志07:57:47
。
更新3
日志并不总是在每一行中包含时间戳。有些行根本不包含任何时间戳。你是如何克服这个问题的?我愚蠢地使用了 awk,并且错过了所有没有时间价值的行。有办法避免这个问题吗?
就像这就是我的意思。
2023-08-07 09:20:35 0123456789 INFO CustomerLogoutResource:95 - Entering logout api.
2023-08-07 09:20:35 0123456789 ERROR AppExceptionMapper:87 - Exception has been thrown by container
2023-08-07 09:20:35 0123456789 ERROR AppExceptionMapper:555 - Unchecked Exception
java.lang.NullPointerException
at NullPointerExceptionExample.printLength(NullPointerExceptionExample.java:3)
at NullPointerExceptionExample.main(NullPointerExceptionExample.java:8)
答案1
如果 10:00 到 11:00 之间没有登录,这种方法无法找到11:00
to的行,并且如果 13:00 到 14:00 之间没有登录,则将报告之后的所有行(并且至少有10 到 11 之间的一个)。13:00
14:00
对于这种事情,最好对时间与边界进行词法比较。
例如,如果时间在第三个字段中:
awk '$3 >= "10:00:00" && $3 < "13:00:00"'
如果您不知道时间在队列中的哪个位置,您可以这样做:
perl -lne 'print if /\b\d\d:\d\d:\d\d\b/ &&
$& ge "10:00:00" &&
$& lt "13:00:00"'
或者:
LC_ALL=C awk 'match($0, /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/) && \
(t = substr($0, RSTART, 8)) >= "10:00:00" && \
t < "13:00:00"'
这些报告了在该范围内具有时间戳的行。如果带有时间戳的行之间有没有时间戳的行,并且您希望报告它们,则可以使用beginning-condition, end-condition {action}
问题中的方法,但再次使用比较而不是正则表达式匹配,或者手动进行状态切换,以继续排除上限:
LC_ALL=C awk -v beg=10:00:00 -v end=13:00:00 '
match($0, /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/) {
t = substr($0, RSTART, 8)
if (t >= end) selected = 0
else if (t >= beg) selected = 1
}
selected'
答案2
该模式/10:..:/
匹配数字 10、两个分隔符:
以及它们之间的任意两个字符。因此它将匹配一个时间(输入行内的任何位置),例如10:35:22
。但它也会匹配包含 的行This10:ZZ:Camels
,因此这不是一个很好的测试。
更好的模式可能是/10:[0-5][0-9]:[0-5][0-9]/
,它检查分钟和秒是否在 00-59 范围内。但检查时间是否在特定字段中,或者当时是否有空格,或者(包括)接近记录的开头也可能会有所帮助。您可以发布一些示例输入行,以便我们更好地了解需要什么。
用逗号分隔两个模式会在检测到第一个模式时“打开”匹配,而在检测到第二个模式时“关闭”匹配。它将匹配这些事件之间的所有行(包括),即使它们根本不包含日期。
这与单一模式非常不同/1[0-2]:[0-5][0-9]:[0-5][0-9]/
,单一模式只匹配 10:00:00 到 12:59:59 之间的各个行,无论它们碰巧是什么顺序。
答案3
awk 模式:
/regA/,/regB/
从匹配 regA 的第一行到匹配 regB 的第一行都为 true。和往常一样,当某些内容与表达式匹配时:如果表达式后面没有任何内容{ actions }
来精确说明匹配时要执行的操作,则默认操作是:打印表达式为 true 的行。
现在他们选择了:
/10:..:/, /13:..:/
更加确定您匹配 10:mm:ss 而不是 hh:10:ss。 (他们通过假设任何时间引用都是 : hh:mm:ss 来做到这一点,并且小时之前没有“:”......这并不总是正确的,具体取决于所使用的日期格式。正如所说在评论中,它也可以匹配其他东西。
如果您知道行的开头始终是:
YYYY-MM-DDThh:mm:ss+hh:mm
# For exemple:
# 2023-07-17T11:14:02+02:00 , which is following internationnal recommendations
# of displaying date and time (and timezone)
您可以更紧密地匹配:
/^2023-07-17T10:/,/^2023-07-17T13:/
并确保仅从行的开头 (^) 开始匹配,而不是从行中可能出现的任何位置进行匹配。
答案4
这是一个可能的解决方案,它选择日志文件中两个时间戳之间的日志。此脚本假定日志文件具有以空格分隔的列,并且第二列包含格式为 的时间戳HH:MM:SS
。可能不是最优雅的,但至少是清晰的。
awk -F" " '$2 >= "09:00:00" && $2 <= "12:00:00"' server.log
-F" "
将字段分隔符设置为空格字符。$2
指输入文件每行中的第二个字段(在这种情况下,字段之间用空格分隔)。>= "09:00:00"
检查第二个字段的值是否大于或等于“09:00:00”。&&
组合条件的逻辑运算符。意思是“和”$2 <= "12:00:00"
检查第二个字段的值是否小于或等于“12:00:00”。sever.log
是你的输入文件
方案验证
对于server.log
看起来像这样的:
2023-07-18 08:55:32 - Log entry 1
2023-07-18 09:10:15 - Log entry 2
2023-07-18 10:30:47 - Log entry 3
2023-07-18 11:45:02 - Log entry 4
2023-07-18 12:05:21 - Log entry 5
2023-07-18 13:20:33 - Log entry 6
输出:
[get@me test]$ awk -F" " '$2 >= "09:00:00" && $2 <= "12:00:00"' server.log
2023-07-18 09:10:15 - Log entry 2
2023-07-18 10:30:47 - Log entry 3
2023-07-18 11:45:02 - Log entry 4