【问题标题】:perl awk OR sed, search between two timestampsperl awk OR sed,在两个时间戳之间搜索
【发布时间】:2014-06-27 16:10:28
【问题描述】:

我有一个包含以下示例文本的文件。 (实际文字很大)。

2014/05/08-19:15:44.544824-<String1>
2014/05/08-19:21:54.544824-<String2>
2014/05/08-19:34:59.564461-<String3>

我必须在两个时间戳之间提取数据,例如 19:15:00 - 19:20:00 等等,直到 eof。我尝试过使用 sed & awk,但问题是在某些时候它们会给出所有的东西。 (例如,他们会从 19:15:00 --> EOF 开始分发所有内容)。我使用的命令是

awk '/19:15:00/,/19:20:00/' InputFile

sed '/19:15:00/,/19:20:00/p' Inputfile.

关于如何在 perl 或 sed & awk 中执行此操作的任何想法,这实际上可能有效吗?错误的输出是否与时间戳的格式有关? (只是想)

PS。我正在使用以下代码制作时间戳。 (这可能是因为本地时间功能吗?

$curr = timelocal(0, 0, 0, (split /\//, $ARGV[0])[1], (split /\//, $ARGV[0])[0]-1, (split /\//, $ARGV[0])[-1]);
$currentTime = strftime "%H:%M:%S", localtime($curr);

【问题讨论】:

  • 我知道你的数据比较大,但是没有理由只给出三行样本。对我们测试我们的解决方案没有任何用处,并且您没有指出,例如,数据是否已经按时间升序排序。我不知道限制是什么,但是您可以发布大量代码行。如果样本的大小会干扰帖子的可理解性,那么它是否会缩小为滚动块,所以请不要限制示例数据的大小
  • 谢谢,这是个好建议,我会记住的。

标签: perl time awk sed timestamp


【解决方案1】:

使用 perl 单行。记录时间,然后进行比较。

perl -ne '$t = /(\d+:[\d:.]+)/ ? $1 : undef; 
    print if $t ge "19:15:00" && $t le "19:20:00";' file.txt

【讨论】:

  • 错误........ perl -ne '$t = /(\d+:[\d:.]+)/ ? $1 : 未定义;打印 if $t ge '19:15:00' && $t le '19:20:00';' /tmp/Output.txt 语法错误在 -e 第 1 行,靠近“19:”
  • @user3195304 是的,只需要为 eval 中的字符串使用不同的分隔符。已更新。
  • 我最初单引用了'19:15:00' 字符串。如果不转义,这将无法工作,因为 eval 用单引号 -e '...' 括起来。最简单的解决方案是只使用双引号而不是 "19:15:00",我已在帖子中进行了更新。或者,也可以使用q{19:15:00},这有时是一个不错的选择,以防在 windows 和 unix 环境之间交换单行。
  • @Miller:什么eval-e 选项不执行 eval
  • @Miller:啊,我明白你的意思了:你最初使用带有单引号嵌入字符串的-e '...'。我认为将-e 选项视为eval 是很危险的,因为两者非常不同,例如传递给eval 的任何字符串都不会使程序崩溃,但-e 参数必须 干净地编译和执行。我更喜欢将-e 视为--execute
【解决方案2】:

您在上面显示的 awk 和 sed 命令不起作用,因为它们在进行模式匹配——它们没有按时间顺序相互比较时间戳(即,如果它没有看到确切的 19:20 :00 字符串,即使沿途看到 19:21:00 也会一直持续到最后)。

您可能可以在 perl 中使用类似于您在生成时间戳的末尾显示的两行的内容来执行此操作,但反过来解析它们,将它们转换为时间对象并比较它们的值。

【讨论】:

  • 很棒的信息。现在我明白了。我正在尝试使用 perl 触发器或 perl one liner。但失败到现在!有什么想法吗?
【解决方案3】:

这可能并不明显,但是具有按数量级降序排列的固定宽度字段的日期/时间表示(如 ISO 8601 %Y-%m-%dT%H:%M:%S)可以简单地作为字符串进行比较,因此 '19:21:54.544824' gt '19:20'为真,而19:15:44.544824 lt '19:15'

这意味着您可以像这样使用split 来提取字段并进行文字比较

use strict;
use warnings;

while (<DATA>) {
  my $time = (split /-/)[1];
  print if $time ge '19:15' and $time le '19:20';
}

__DATA__
2014/05/08-19:15:44.544824-<String1>
2014/05/08-19:21:54.544824-<String2>
2014/05/08-19:34:59.564461-<String3>

输出

2014/05/08-19:15:44.544824-<String1>

【讨论】:

    【解决方案4】:

    为什么这么复杂?

    $ awk -F'[-.]' '"19:15:00"<=$2 && $2<="19:20:00"' file
    2014/05/08-19:15:44.544824-<String1>
    

    如果文件已排序,则可读性会降低,但效率会更高:

    $ awk -F'[-.]' '$2>"19:20:00"{exit} $2>="19:15:00"' file
    2014/05/08-19:15:44.544824-<String1>
    

    【讨论】:

      【解决方案5】:

      使用 awk

      awk '{gsub(/:/,X,$2)}$2>=191500&&$2<=192000' FS="[-.]" file
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-09
        • 1970-01-01
        • 2014-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-07
        • 1970-01-01
        相关资源
        最近更新 更多