Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何使用Perl搜索文件中两个时间戳之间的行?_Regex_Perl_Timestamp - Fatal编程技术网

Regex 如何使用Perl搜索文件中两个时间戳之间的行?

Regex 如何使用Perl搜索文件中两个时间戳之间的行?,regex,perl,timestamp,Regex,Perl,Timestamp,在Perl中,我试图读取一个日志文件,只打印在两个特定时间之间有时间戳的行。时间格式为hh:mm:ss,这始终是每个日志上的第三个值。例如,我将搜索介于12:52:33到12:59:33之间的行 我是Perl新手,甚至不知道该走哪条路来编程。我很确定这将使用某种类型的正则表达式,但就我的一生而言,我甚至无法开始理解这将是什么。有人能帮我吗 另外,为了使这一点更加困难,我必须使用核心Perl模块,因为我的公司不允许我使用任何其他模块,除非它们经过测试和验证,否则脚本可能与之交互的任何系统都不会受到

在Perl中,我试图读取一个日志文件,只打印在两个特定时间之间有时间戳的行。时间格式为hh:mm:ss,这始终是每个日志上的第三个值。例如,我将搜索介于12:52:33到12:59:33之间的行

我是Perl新手,甚至不知道该走哪条路来编程。我很确定这将使用某种类型的正则表达式,但就我的一生而言,我甚至无法开始理解这将是什么。有人能帮我吗


另外,为了使这一点更加困难,我必须使用核心Perl模块,因为我的公司不允许我使用任何其他模块,除非它们经过测试和验证,否则脚本可能与之交互的任何系统都不会受到不良影响

在伪代码中,您可以执行以下操作:

  • 逐行读取文件:
    • 分析此行的时间戳
    • 如果小于开始时间,请跳到下一行
    • 如果大于结束时间,请跳到下一行
    • 否则:这是你想要的一行:打印出来
这对于您的需要来说可能太高级了,但是
在这里很有用

对于从stdin读取文件,这是常规模式:

while (my $line = <>)
{
     # do stuff...
}

如果文件中的每一行都有时间戳,则在“sed”中可以写入:

sed -n '/12:52:33/,/12:59:33/p' logfile
这将与相关线路相呼应

有一个Perl程序s2p,它将“sed”脚本转换为Perl

基本Perl结构大致如下:

my $atfirst = 0;
my $atend = 0;
while (<>)
{
    last if $atend;
    $atfirst = 1 if m/12:52:33/;
    $atend = 1 if m/12:59:33/;
    if ($atfirst)
    {
        process line as required
    }
}
my$atfirst=0;
我的$atend=0;
而()
{
最后如果$atend;
如果m/12:52:33/,则$atfirst=1;
如果m/12:59:33/,则$atend=1;
如果($atfirst)
{
按要求生产线
}
}

请注意,编写时,代码将处理与结束标记匹配的第一行。如果您不想这样做,请在测试后移动“最后一个”。

如果日志文件按天分隔,您可以将时间戳转换为秒,并进行比较。(如果不是,请使用中的技术。)

说你的日志是

12:52:32 outside 12:52:43 strictly inside 12:59:33 end 12:59:34 outside 12:52:32外面 12:52:43严格地说是在里面 12:59:33结束 12:59:34外面 然后

#! /usr/bin/perl

use warnings;
use strict;

my $LOGPATH = "/tmp/foo.log";

sub usage { "Usage: $0 start-time end-time\n" }

sub to_seconds {
  my($h,$m,$s) = split /:/, $_[0];
  $h * 60 * 60 +
       $m * 60 +
            $s;
}

die usage unless @ARGV == 2;
my($start,$end) = map to_seconds($_), @ARGV;

open my $log, "<", $LOGPATH or die "$0: open $LOGPATH: $!";
while (<$log>) {
  if (/^(\d+:\d+:\d+)\s+/) {
    my $time = to_seconds $1;
    print if $time >= $start && $time <= $end;
  }
  else {
    warn "$0: $LOGPATH:$.: no timestamp!\n";
  }
}
#/usr/bin/perl
使用警告;
严格使用;
my$LOGPATH=“/tmp/foo.log”;
子用法{“用法:$0开始时间结束时间\n”}
分到秒{
我的($h,$m,$s)=拆分/:/,$0];
$h*60*60+
$m*60+
$s;
}
除非@ARGV==2,否则使用模具;
my($start,$end)=映射到秒($)@ARGV;

打开我的$log,“如果开始和结束时间已知,则需要一个带有触发器运算符的Perl one liner:

perl -ne 'print if /12:52:33/../12:59:33/' logFile
如果需要一些基本逻辑来确定开始和结束时间,则将一行代码“展开”为正式脚本:

use strict;
use warnings;

open my $log, '<', 'logFile';

my $startTime = get_start_time();  # Sets $startTime in hh:mm:ss format
my $endTime = get_end_time();      # Sets $endTime in hh:mm:ss format

while ( <$log> ) {

    print if /$startTime/../$endTime/;
}
使用严格;
使用警告;

打开我的$log,'第三个值是什么意思?第三个字段?你能发布一个日志行的示例吗?这将有助于澄清问题。如果你想要O(logN)而不是O(N),你可以使用二进制搜索而不是读取每一行(假设日志文件按时间戳排序)。这样的任务非常适合触发器运算符。如果没有时间戳与开始或结束时间完全匹配的行,则该条件将失败。@Ether:同意。当OP没有指定有关问题的足够信息时,会发生这种情况。
perl -ne 'print if /12:52:33/../12:59:33/' logFile
use strict;
use warnings;

open my $log, '<', 'logFile';

my $startTime = get_start_time();  # Sets $startTime in hh:mm:ss format
my $endTime = get_end_time();      # Sets $endTime in hh:mm:ss format

while ( <$log> ) {

    print if /$startTime/../$endTime/;
}
use strict;
use warnings;
use autosplit;

open my $log, '<', 'logFile';

my $startTime = get_start_time();  # Sets $startTime in hh:mm:ss format
my $endTime = get_end_time();      # Sets $endTime in hh:mm:ss format

while ( <$log> ) {

    my $time = (split /,/, $_)[2];      # Assuming fields are comma-separated
                                        # and timelog is 3rd field

    last  if $time gt $endTime;         # Stop when stop time reached
    print if $time ge $startTime;
}