【问题标题】:AWK read-ahead pattern captureAWK 预读模式捕获
【发布时间】:2020-01-11 05:19:19
【问题描述】:

为了清楚起见,我正在重新编辑 -- 感谢大家的意见。

我正在使用 awk 进行一些脚本文件处理并尝试捕获时间戳的值,然后将其追溯应用到日志中 --

示例日志--

20191127:20:22:40 023116-[INFO]:-Starting backup of database wan
20191127:20:22:40 023116-[DEBUG]:-Creating backup directories
20191127:20:22:40 023116-[DEBUG]:-Getting database size
20191127:20:22:40 023116-[INFO]:-Backup Timestamp = 20191127202240
20191127:20:22:42 023116-[DEBUG]:-Beginning cleanup
20191127:20:22:42 023116-[DEBUG]:-Cleanup complete
20191127:20:22:42 023116-[INFO]:-Backup completed successfully
20191127:21:22:40 023116-[INFO]:-Starting backup of database tew
20191127:21:22:40 023116-[DEBUG]:-Creating backup directories
20191127:21:22:40 023116-[DEBUG]:-Getting database size
20191127:21:22:40 023116-[INFO]:-Backup Timestamp = 20191127212240
20191127:21:22:42 023116-[DEBUG]:-Beginning cleanup
20191127:21:22:42 023116-[DEBUG]:-Cleanup complete
20191127:22:22:40 023116-[INFO]:-Starting backup of database tree
20191127:22:22:40 023116-[DEBUG]:-Creating backup directories
20191127:22:22:40 023116-[DEBUG]:-Getting database size
20191127:22:22:40 023116-[INFO]:-Backup Timestamp = 20191127222240
20191127:22:22:42 023116-[DEBUG]:-Beginning cleanup
20191127:22:22:42 023116-[DEBUG]:-Cleanup complete
20191127:22:22:42 023116-[INFO]:-Backup completed successfully

一个文件中可能有多次运行——我不能使用日期/时间,因为目录创建可能会推迟备份时间戳。

为了使模式更加复杂,备份总是会遇到清理,但可能并不总是成功。

我试图使用 awk 来执行此操作 --

如果我使用:

awk '/Timestamp/{ f=$5 }{ if ( f!="" ) print f,$0 }

那么我不仅会错过前 3 行,而且最终会用错误的邮票标记下一份工作的前 3 行。

我以为我可以使用 getline,但它会消耗行数 - 由于处理顺序,它不太正确...

所需的输出是用时间戳标记所有作业行

20191127202240 20191127:20:22:40 023116-[INFO]:-Starting backup of database wan
20191127202240 20191127:20:22:40 023116-[DEBUG]:-Creating backup directories
20191127202240 20191127:20:22:40 023116-[DEBUG]:-Getting database size
20191127202240 20191127:20:22:40 023116-[INFO]:-Backup Timestamp = 20191127202240
20191127202240 20191127:20:22:42 023116-[DEBUG]:-Beginning cleanup
20191127202240 20191127:20:22:42 023116-[DEBUG]:-Cleanup complete
20191127202240 20191127:20:22:42 023116-[INFO]:-Backup completed successfully
20191127212240 20191127:21:22:40 023116-[INFO]:-Starting backup of database tew
20191127212240 20191127:21:22:40 023116-[DEBUG]:-Creating backup directories
20191127212240 20191127:21:22:40 023116-[DEBUG]:-Getting database size
20191127212240 20191127:21:22:40 023116-[INFO]:-Backup Timestamp = 20191127212240
20191127212240 20191127:21:22:42 023116-[DEBUG]:-Beginning cleanup
20191127212240 20191127:21:22:42 023116-[DEBUG]:-Cleanup complete
20191127222240 20191127:22:22:40 023116-[INFO]:-Starting backup of database tree
20191127222240 20191127:22:22:40 023116-[DEBUG]:-Creating backup directories
20191127222240 20191127:22:22:40 023116-[DEBUG]:-Getting database size
20191127222240 20191127:22:22:40 023116-[INFO]:-Backup Timestamp = 20191127222240
20191127222240 20191127:22:22:42 023116-[DEBUG]:-Beginning cleanup
20191127222240 20191127:22:22:42 023116-[DEBUG]:-Cleanup complete
20191127222240 20191127:22:22:42 023116-[INFO]:-Backup completed successfully

我假设最简单的方法是缓冲行,然后追溯应用时间戳 --

类似于 --

{
  if ($0 ~ /Backup Timestamp/) { 
    timestamp = $NF; for (i=0; i<nb; i++) { 
      print timestamp,backup[i] 
     }; 
     nb=0; 
  }
  if (timestamp == "") { 
    backup[nb++] = $0 
  }
  else { 
    print timestamp,$0 
  }
}

【问题讨论】:

  • 我对你的最终目标有点困惑。您是说您需要找到Timestamp 行,然后确保备份时间戳与截至该点的日志条目的时间相同,然后使用该时间戳输出截至该点的所有条目?您能否展示几行您的预期输出并指出它与原始输出有何不同?
  • 一项工作究竟从哪一行开始和结束? Starting backup of database tew 是工作的开始,Backup completed successfully 是结束?你想用它做什么?
  • edit 您的问题是为了阐明您的要求并根据您发布的输入提供预期的输出。在每个 Timestamp 行之后是否总是有一行只有 ... ?如果不摆脱它们并确保您在问题中提供的示例输入真正看起来像您的实际数据。使用 getline 几乎肯定是错误的方法,请参阅 awk.freeshell.org/AllAboutGetline
  • 我用一些更好的例子和预期的输出更新了这个问题。 Ty 为您跟进。

标签: bash awk


【解决方案1】:

我理解的方式是您想要为代表成功备份的行加上时间戳。根据您的说法,这些出现在连续 4 行中,最后一行包含时间戳。

执行此操作的方法是使用模运算符(%) 跟踪数组中的最后 4 条记录。这看起来像这样:

awk '{a[FNR%4] = $0}' logfile

在上面,我们实际上什么都不做,除了跟踪最后 4 行。现在我们可以添加一个额外的模式-动作对来执行预期的结果:

awk '{a[FNR%4] = $0}
     /Backup Timestamp/{
        tstamp=$NF
        for(i=1;i<=4;++i) print tstamp,a[(FNR+i)%4]
     }' logfile

创建输出"

20191127202240 20191127:20:22:40 023116-[INFO]:-Starting backup of database wan
20191127202240 20191127:20:22:40 023116-[DEBUG]:-Creating backup directories
20191127202240 20191127:20:22:40 023116-[DEBUG]:-Getting database size
20191127202240 20191127:20:22:40 023116-[INFO]:-Backup Timestamp = 20191127202240
20191127212240 20191127:21:22:40 023116-[INFO]:-Starting backup of database tew
20191127212240 20191127:21:22:40 023116-[DEBUG]:-Creating backup directories
20191127212240 20191127:21:22:40 023116-[DEBUG]:-Getting database size
20191127212240 20191127:21:22:40 023116-[INFO]:-Backup Timestamp = 20191127212240

【讨论】:

  • 这是完美的功能和简洁。泰。我可以看到,在前向模式可变的情况下,硬编码的4 可以替换为基于 NR/FNR 的变量。
  • 我实际上需要包含工作的所有行,但这给了我需要的信息。
【解决方案2】:

我认为您的问题相当于您的时间戳之前可以有多少行,并且将这些行数存储在 awk 中好吗?您可以使用以下内容存储行:

{
        if ($0 ~ /TimeStamp/) {
                f = $5;
                for (i=0; i < nb; i++) {
                        print f,backup[i]
                }
                nb=0;
        }
        if (f == "") {
                backup[nb++] = $0
        } else {
                print f,$0
        }
}

【讨论】:

  • 这确实通过存储为数组来完成任务-非常感谢您的回答-看到同一问题的多种解决方案总是很好。
  • 如果您在问题中包含预期输出等,您可能会看到更多解决方案,甚至可能是更好的解决方案,idk。
猜你喜欢
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2017-03-05
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多