如果时间戳匹配,我很难找到一种方法将下一行附加到当前行。到目前为止,这是我的代码:
open(FH, "error_log:);
@data = <FH>
foreach $line (@data) {
if ( ($line =~ /notice/)) {
$line =~ s/ /,/g;
my @L1 = split(/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy,
+|rd,|wr,|ka,|log,|dns,|cls,|bsy:,|in,|/, $line);
$line =~ s/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy,|rd,|
+wr,|ka,|log,|dns,|cls,|bsy:,|in,//g;
print $line;
请注意,我只打印以查看输出。输出如下:
Wed,Jun,13,10:40:35,2012,758,42,0,29,11,0,0,2
Wed,Jun,13,10:40:35,2012,29,mod_was_ap22_http.c
Wed,Jun,13,10:41:35,2012,761,39,0,34,5,0,0,0
Wed,Jun,13,10:41:35,2012,34,mod_was_ap22_http.c
Wed,Jun,13,10:42:35,2012,769,31,0,22,6,0,0,3
Wed,Jun,13,10:42:35,2012,22,mod_was_ap22_http.c
Wed,Jun,13,10:43:35,2012,754,46,0,29,17,0,0,0
我想将数字(第二行29)以csv形式放在第一行对应的时间戳之后。可以删除该行的其余部分。如果该行下面没有任何内容(例如最后一行),我想追加零。谢谢您的帮助。
以下是所请求的输入数据的一部分:
[Wed Jun 13 01:41:24 2012 [error [client 10.119.84.9 File does not exist: /ebiz/b2b/IHS70prd/htdocs/offline.b2bonline.html
[Wed Jun 13 01:41:25 2012 [error [client 10.119.84.9 File does not exist: /ebiz/b2b/IHS70prd/htdocs/offline.b2bonline.html
[Wed Jun 13 01:41:25 2012 [error [client 10.119.84.8 File does not exist: /ebiz/b2b/IHS70prd/htdocs/offline.b2bonline.html
[Wed Jun 13 01:41:28 2012 [error [client 10.119.116.8 File does not exist: /ebiz/b2b/IHS70prd/htdocs/offline.b2bonline.html
[Wed Jun 13 01:41:28 2012 [error [client 10.119.84.8 File does not exist: /ebiz/b2b/IHS70prd/htdocs/offline.b2bonline.html
[Wed Jun 13 01:41:34 2012 [notice mpmstats: rdy 786 bsy 14 rd 0 wr 11 ka 3 log 0 dns 0 cls 0
[Wed Jun 13 01:41:34 2012 [notice mpmstats: bsy: 11 in mod_was_ap22_http.c
[Wed Jun 13 01:41:34 2012 [error [client 10.119.84.9 File does not exist: /ebiz/b2b/IHS70prd/htdocs/offline.b2bonline.html
[Wed Jun 13 01:41:35 2012 [error [client 10.119.84.9 File does not exist: /ebiz/b2b/IHS70prd/htdocs/offline.b2bonline.html
答案 0 :(得分:1)
你的输入很奇怪。通常,我看到匹配的方括号。
除此之外,你想要的是这样的:
# This assumes you have Perl 5.10 or autodie installed: failures in open, readline,
# or close will die automatically
use autodie;
# chunks of your input to ignore, see below...
my %ignorables = map { $_ => 1 } qw(
[notice mpmstats: rdy bsy rd wr ka log dns cls bsy: in
);
# 3-arg open is safer than 2, lexical my $fh better than a global FH glob
open my $error_fh, '<', 'error_log';
# Iterates over the lines in the file, putting each into $_
while (<$error_fh>) {
# Only worry about the lines containing [notice
if (/\[notice/) {
# Split the line into fields, separated by spaces, skip the %ignorables
my @line = grep { not defined $ignorables{$_} } split /\s+/;
# More cleanup
s/^\[//g for @line; # remove [ from [foo
# Output the line
print join(",", @line);
# Assuming the second line always has "in" in it,
# but this could be whatever condition that fits your data...
if (/\bin\b/) { # \b matches word edges, e.g., avoids matching "glint"
print "\n";
}
else {
print ",";
}
}
}
close $error_fh;
我没有编译这个,所以我无法保证我在某个地方没有拼写错误。
这里的关键是你在没有换行符的情况下执行第一个print
,但以逗号结束。然后,在检测到这是第二行时添加换行符。
您可以在循环外声明@line
并使用它来累积字段,直到您需要在结尾处使用换行符输出它们。
答案 1 :(得分:0)
使用perl
的一种方法。它省略了不包含 [notice 的行。对于每一行匹配,它会递增一个变量,并根据它是奇数还是偶数( [notice >第二次出现)来保存数组中的不同字段。
perl -ane '
next unless $F[5] eq q|[notice|;
++$notice;
if ( $notice % 2 != 0 ) {
push @data, @F[0..4, 8, 10, 12, 14, 16, 18, 20, 22];
next unless eof;
}
push @data, (eof) ? 0 : $F[8];
$data[0] =~ s/\A\[//;
printf qq|%s\n|, join q|,|, @data;
@data = ();
' infile
假设infile
包含您的问题内容,则输出为:
Wed,Jun,13,01:41:34,2012,786,14,0,11,3,0,0,0,11