【问题标题】:Howto grep over months with defined start and end date如何在定义的开始和结束日期的几个月内grep
【发布时间】:2016-09-08 09:28:28
【问题描述】:

所以这是我的问题:我有很大的日志文件,并且想要一个脚本来 grep 某些时间段并将它们安全到一个文件(排序),基本上

bash script.sh Jul 4 Sep 30

例如会返回

Sep 30 user0 logged in
Sep 15 user1 logged in
Aug 6 user0 logged in
Aug 3 user1 logged in
Jul 28 user2 logged in
Jul 27 user2 logged in
Jul 4 user0 logged in

我的第一次尝试是每个月和日期都有自己的变量,比如

bash script.sh Jul 4 Sep 3 0

所以我可以在开始月份(7 月)使用 $1,在开始日期(4)中使用 $2,依此类推

for logs in logs*
do
grep -qEe "^\"$1\" [\"$2\"-9]\s" $messages >> result.txt
done

获取 7 月 4 日至 9 日的所有日志,但我不知道如何获取整个时间段的日志,这些时间段不在同一个月内,也不在 1-9 或 10-19 等期间
非常感谢任何帮助!

编辑:

正如一些人所问的,这是我的日志文件的样子(只是更大且未排序):

Sep 30 user0 logged in
Jul 27 user2 logged in
Aug 6 user0 logged in
Aug 31 user1 logged in
Jul 8 user2 logged in
Sep 5 user1 logged in
Jul 27 user2 logged in
Jul 14 user0 logged in
[...]

【问题讨论】:

  • 以日志文件中的几行为例。
  • 这是 Gnu awk 中的一个:stackoverflow.com/questions/39220666/…
  • 日志文件看起来像第二个代码段,只是有更多行(未排序)以及其他日期,例如 7 月 3 日用户 0 登录或 5 月 15 日用户 1 登录
  • @JamesBrown 我不熟悉 awk,尽管问题很相似,但没有对此解决方案的解释
  • 大声笑,将您想要的开始和结束时间设置为注释,这是您的 mktime 行接近尾声:mktime("2016 "mons[$1]" "$2" 00 00 00") 但当然开箱即用更容易。只是想帮忙。

标签: regex bash date grep


【解决方案1】:

这是我的看法:

#/bin/bash

year="$(date +"%Y")"
start="$(date -d"$1 $2, $year" +'%s')"
end="$(($(date -d"$3 $4, $year" +'%s')+86400))"
for log in logs*; do
    while IFS= read -r line; do
        d="$(date -d"$(cut -d' ' -f1,2 <<< "$line"), $year" +'%s')"
        if (( $start <= $d && $d < $end )); then
            echo "$s"
        fi
    done < "$log"
done

你这样运行它:./script.sh Jul 04 Sep 03。由于日志中不包含年份,因此它假定所有日期(包括命令行中的日期)都是当前年份的。这可能不是最佳解决方案,但它确实有效。它依赖于date,它反复调用它来将日期解析为unix时间戳。 unix 时间戳很好,因为它们只是数字,因此可以用于数字比较。

【讨论】:

  • 谢谢,这看起来非常接近我想要的。嗯,但我不明白第 5 行和第 6 行(d=,我认为这是转换日志中的日期和时间?)你能解释一下吗?也因为我的日志看起来与 Thu Aug 25 15:19:01 2016 [ info ]: xvbdfdre dfdfd (no day names or time and year) 不同:/
  • 如果您不提供日志中的一行示例,我无法帮助您。你不理解的代码行,做字符串操作来提取字符串的日期部分并解析它。
  • 日志文件看起来像第二个代码段,只是有更多的行(未排序)以及其他日期,例如 7 月 3 日用户 0 登录或 5 月 15 日用户 1 登录(我编辑了我的帖子,所以大家可以看到)
  • 我现在几乎可以正常工作但我看到像“Aug 8”这样的单个数字的行确实有两个(!)空格,比如 Aug--6 user0 登录而不是 Aug-6 user0 登录(我使用 - 用于显示空格,在日志中没有 - 在 8 月到 8 日之间)。问题是 cut 使用单个空格作为字段一和二之间的分隔符。知道如何解决这个问题吗?
  • 好的,我找到了一个使用 trimm 的解决方案,类似于 date +%-m%d -d "$(tr -s ' ' &lt;&lt;&lt; "Jul 5 jkxjkakjb" | cut -d' ' -f1,2)",它将登录到 Aug-6 的 Aug--6 user0 (我使用 - 用于显示空格,在日志中没有- 在 8 月到 6 日之间),然后在这种情况下计算到日期 mdd 705
【解决方案2】:
$ range="Jul 4 Sep 30"
$ awk -v range="$range" '
BEGIN {
    numMths = split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",m)
    for (i in m) {
        mths[m[i]] = i
    }

    split(range,r)
    beg = sprintf("%02d%02d", mths[r[1]], r[2])
    end = sprintf("%02d%02d", mths[r[3]], r[4])
}
{ cur = sprintf("%02d%02d", mths[$1], $2) }
(cur >= beg) && (cur <= end) { vals[$1,$2] = $0 }
END {
    for (mthNr=numMths; mthNr>0; mthNr--) {
        for (dayNr=31; dayNr>0; dayNr--) {
            date = m[mthNr] SUBSEP dayNr
            if (date in vals) {
                print vals[date]
            }
        }
    }
}
' file
Sep 30 user0 logged in
Sep 5 user1 logged in
Aug 31 user1 logged in
Aug 6 user0 logged in
Jul 27 user2 logged in
Jul 14 user0 logged in
Jul 8 user2 logged in

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 2022-07-13
    • 1970-01-01
    • 2019-02-25
    相关资源
    最近更新 更多