【问题标题】:Match date on logfile and print line with awk匹配日志文件上的日期并使用 awk 打印行
【发布时间】:2015-01-25 03:01:17
【问题描述】:

我有一个日志文件,在其他 100 行中可能包含以下行

hosta: Info: Tue Nov 25  19:44:39 2014>
User jwayman at position 170.198.3.141 disconnected 

hosta: Info: Tue Nov 23  19:44:39 2014>
User jho at position 170.198.3.141 disconnected 

hosta: Info: Tue Nov 26  19:44:39 2014>
User jho at position 170.198.3.141 disconnected 

我需要查找“断开连接”的出现,然后如果日期(从它上面的行)与今天的日期匹配,那么我想打印以下信息:

user jho disconnected from server "hosta"

所以我需要从两行中提取数据,然后对其进行处理。 我正在考虑在数组中执行此操作并将所有出现的事件分配给数组中的变量。 但我希望有人可以介绍一种更简单的方法,可能是grepawk

【问题讨论】:

  • 如果 23、25、26 日都是星期二,那你的日志软件有问题!
  • 只是我这边的一个错字

标签: awk sed grep tr


【解决方案1】:

使用 GNU awk 实现 gensub() 和时间函数:

$ awk -v RS= '
    BEGIN { today=strftime("%a%b%d") }
    (($3$4$5)==today) && /disconnected/ {
        print $8, $9, $NF, "from server \"" gensub(/:/,"\"","",$1)
    }
' file
User jho disconnected from server "hosta"

【讨论】:

    【解决方案2】:

    与 fedorqui 相同的概念(他领先我几分钟),但具有您要求的确切输出,而不仅仅是输入断开的线路。

    awk -v date="$(date "+%a %b %d")" '$2 == "Info:" {
                                           if ($3" "$4" "$5==date) {
                                               s=$1; sub(/:$/,"",s)
                                           } else {
                                               s=""
                                           }
                                           next
                                       }
                                       s && ($NF == "disconnected") {
                                           print "user",$2,"disconnected from server \""s"\""
                                           s=""
                                           next
                                       }'
    

    解释:

    • $2 == "Info: 我们在看Info 行吗
      • if ($3" "$4" "$5==date) {是今天的这条线
      • s=$1; sub(/:$/,"",s) 将服务器分配给s 并去掉结尾的冒号
      • else这是前几天的一条线
      • s="" 取消设置我们的服务器变量。
      • next 跳到下一行
    • s && ($NF == "disconnected") 我们有保存的服务器吗,这是断线吗
      • print "user",$2,"disconnected from server \""s"\"" 打印所需的输出
      • s="" 取消设置我们的服务器变量。
      • next跳到下一行

    【讨论】:

    • 谢谢我试试这个
    • 嗨。 Thx 这个工作并且还打印主机名。试图弄清楚所有的 awk 选项以及这个命令是如何工作的。
    • @theuniverseisflat 这里的逻辑与 fedorqui 的回答(他解释)中的逻辑基本相同,不同之处在于它捕获了服务器(在 s 中)并在输出行中使用它。
    • thx 我正在查看你们的两个回复.. 我知道你们两个很容易.. 但是这些组合让我失望了
    • @theuniverseisflat 您具体理解什么有困难?
    【解决方案3】:

    您可以使用以下内容:

    awk -v today="$(date "+%a %b %d")" '$3 FS $4 FS $5 == today {f=1; next}
                                        f && /disconnected/ {print}
                                        f=0 ' file
    

    说明

    • $(date "+%a %b %d") 返回格式为 Wed Nov 26
    • $3 FS $4 FS $5 == today {f=1; next} 检查当前行是否具有这种格式。如果是这样,则会激活标志 f
    • f && /disconnected/ {print} 如果设置了标志并且该行包含disconnected,则打印它。
    • f=0 取消设置标志。

    测试

    示例文件:

    $ cat a
    hosta: Info: Tue Nov 25  19:44:39 2014>
    User jwayman at position 170.198.3.141 disconnected 
    
    hosta: Info: Tue Nov 23  19:44:39 2014>
    User jho at position 170.198.3.141 disconnected 
    
    hosta: Info: Wed Nov 26  19:44:39 2014>
    User jho at position 170.198.3.141 disconnected 
    
    hosta: Info: Wed Nov 26  19:44:39 2014>
    User jho at position 170.198.3.141 here
    

    检查脚本:

    $ awk -v today="$(date "+%a %b %d")" '$3 FS $4 FS $5 == today {f=1; next} f && /disconnected/ {print} f=0 ' a
    User jho at position 170.198.3.141 disconnected 
    

    【讨论】:

    • 嗨,这很好用,但我怎样才能打印主机名。第一行的示例玉簪?
    • 嗯,你可以说f=1; server=$1,然后是print server, $0。塔尔是,你抓住了名字,然后把它打印回来。
    • 再次感谢您。我正在查看选项并试图理解逻辑。没有使用过这个选项并且对它的工作方式有一些问题..
    • @theuniverseisflat 让我知道我写的脚本中有什么不清楚的地方!你也可以看看awk的指南:grymoire.com/Unix/Awk.html
    猜你喜欢
    • 2014-03-31
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    相关资源
    最近更新 更多