【问题标题】:awk for date range in secondsawk 以秒为单位的日期范围
【发布时间】:2012-08-03 18:53:41
【问题描述】:

我有一个按日期存储系统状态的记录文件。生成它的脚本通过 cron 运行,因此文件不断变长。我编写了一个脚本,它遍历每一行来处理它,这需要很长时间才能完成。我听说 awk 在处理大型文本文件时要快得多。我的问题是我从来没有使用过它。是否可以使用 awk 获取日期范围内的所有条目?日期都以秒为单位,因为它们是用date +%s 生成的。这是一个输出示例,我希望能够快速找到某个范围内的数据。例如,我怎样才能得到第一列在 1344279903 和 1344280204 之间的所有行?

1344279903 |  0  | 0 | node  |  1
1344279904 |  0  | 0 | node  |  2
1344279905 |  0  | 0 | node  |  3
1344280202 |  0  | 0 | node  |  1
1344280203 |  0  | 0 | node  |  2
1344280204 |  99  | 0 | node  |  3

【问题讨论】:

  • 您正在分析的文件有多大? # 行数和 # 字节数对于确定这样的解决方案是否合适很有用。

标签: bash awk


【解决方案1】:

这是我的看法:

#!/usr/bin/awk -f

BEGIN {
  start=ARGV[1]; ARGV[1]="";
  end=ARGV[2]; ARGV[2]="";
}

$1 < start { next }

$1 > end { exit }

1

这是如何工作的?

Awk 使用一系列“条件{命令}”块应用于每一行输入。 BEGIN 块是在输入开始之前运行的“魔术”块。 (输入结束有一个类似的 END 块,但我们在这里没有使用它。)

  • 在此脚本中,我们的 BEGIN 块根据您的命令行设置“start”和“end”变量,然后清空这些变量,以便 awk 不会尝试将它们解释为输入文件。
  • 下一个条件会导致 awk 跳过开始日期之前出现的任何行。当我们运行 next 时,我们告诉 awk 读取新的输入行并重新开始处理其条件。
  • 下一个条件会导致 awk 在到达要打印的日期范围的末尾时退出。 (当然,这假设您的输入数据是按时间顺序排列的。)
  • 最后一个条件本身就是一个“1”。这是“打印当前行”的 Awk 简写,如果前面的两个条件都不满足,它将执行此操作(因为前面的两个条件都会阻止我们到达脚本中的这一点)。

它在您的示例数据上起作用:

ghoti@pc$ ./awkdate 1344279905 1344280203 data.txt
1344279905 |  0  | 0 | node  |  3
1344280202 |  0  | 0 | node  |  1
1344280203 |  0  | 0 | node  |  2
ghoti@pc$ 

【讨论】:

    【解决方案2】:

    使用 awk?

    awk -F'|' '1344279903 <= $1 && $1 <= 1344280204' file
    

    使用 sed?

    sed -n '/1344279903/,/1344280204/p' file
    

    您可以通过在最后一个打印语句之后显式退出来使 awk 表达式更加高效:

    awk -F'|' '1344279903 <= $1 && $1 <= 1344280204{ print $0; } $1 == 1344280204{ exit; }' file
    

    【讨论】:

      【解决方案3】:

      你可以像这样使用条件表达式:

      awk '$1 >= 1344279903 && $1 <= 1344280204 { print $0 }' data.txt
      

      【讨论】:

      • 哇!我没想到会那么容易。我一直看到不断调用单独脚本文件的 awk 教程,但我根本没有关注它们。非常感谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      • 2022-03-21
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      相关资源
      最近更新 更多