Regex 如何使用Perl搜索文件中两个时间戳之间的行?
在Perl中,我试图读取一个日志文件,只打印在两个特定时间之间有时间戳的行。时间格式为hh:mm:ss,这始终是每个日志上的第三个值。例如,我将搜索介于12:52:33到12:59:33之间的行 我是Perl新手,甚至不知道该走哪条路来编程。我很确定这将使用某种类型的正则表达式,但就我的一生而言,我甚至无法开始理解这将是什么。有人能帮我吗Regex 如何使用Perl搜索文件中两个时间戳之间的行?,regex,perl,timestamp,Regex,Perl,Timestamp,在Perl中,我试图读取一个日志文件,只打印在两个特定时间之间有时间戳的行。时间格式为hh:mm:ss,这始终是每个日志上的第三个值。例如,我将搜索介于12:52:33到12:59:33之间的行 我是Perl新手,甚至不知道该走哪条路来编程。我很确定这将使用某种类型的正则表达式,但就我的一生而言,我甚至无法开始理解这将是什么。有人能帮我吗 另外,为了使这一点更加困难,我必须使用核心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;
}