这个问题与this非常相似,只是我希望尽快做到这一点,只做一次(不幸的是gzip压缩)文件。
给定模式CAPTURE
和输入
1:.........
...........
100:CAPTURE
...........
150:CAPTURE
...........
200:CAPTURE
...........
1000:......
打印:
100:CAPTURE
...........
150:CAPTURE
...........
200:CAPTURE
这可以用正则表达式完成吗?
我依稀记得这种语法不能通过正则表达式捕获,但不太确定正规表达式如今提供了展望等等。
答案 0 :(得分:2)
我会写
gunzip -c file.gz | sed -n '/CAPTURE/,$p' | tac | sed -n '/CAPTURE/,$p' | tac
答案 1 :(得分:2)
您可以缓冲线条,直到看到包含CAPTURE
的行,特别处理第一次出现的图案。
#!/usr/bin/env perl
use warnings;
use strict;
my $first=1;
my @buf;
while ( my $line = <> ) {
push @buf, $line unless $first;
if ( $line=~/CAPTURE/ ) {
if ($first) {
@buf = ($line);
$first = 0;
}
print @buf;
@buf = ();
}
}
通过zcat file.gz | perl script.pl
将输入信息输入此程序。
如果需要的话,当然可以将其塞进单线中......
zcat file.gz | perl -ne '$x&&push@b,$_;if(/CAPTURE/){$x||=@b=$_;print@b;@b=()}'
这可以用正则表达式完成吗?
你的意思是一次性使用一个正则表达式?如果你不介意将整个文件读入内存,请确保......但对于大文件来说,这显然是不。
zcat file.gz | perl -0777ne '/((^.*CAPTURE.*$)(?s:.*)(?2)(?:\z|\n))/m and print $1'
答案 2 :(得分:2)
找到第一个CAPTURE并回顾最后一个。
echo "/CAPTURE/,?CAPTURE? p" | ed -s <(gunzip -c inputfile.gz)
编辑:回答评论和第二(更好?)解决方案。
当您的输入未以换行符结束时,ed
会抱怨,如这些测试所示。
# With newline
printf "1,$ p\n" | ed -s <(printf "%s\n" test)
# Without newline
printf "1,$ p\n" | ed -s <(printf "%s" test)
# message removed
printf "1,$ p\n" | ed -s <(printf "%s" test) 2> /dev/null
我不知道这会给大文件带来的内存复杂性,但你更喜欢流媒体解决方案
您可以使用sed
进行下一步。
继续读行,直到找到第一场比赛。在此期间,只记住读取的最后一行(将其放入保留区域)
现在改变你的策略
将每一行附加到保留区域。你不知道何时冲到下一场比赛。
当您进行下一场比赛时,请调出保持区域并打印出来
我需要一些tweeking来防止第二场比赛打印两次。我通过读取下一行并用该行替换HOLD区域来解决这个问题
总解决方案是
gunzip -c inputfile.gz | sed -n '1,/CAPTURE/{h;n};H;/CAPTURE/{x;p;n;h};'
当您不喜欢sed
持有空间时,您可以使用awk
实现相同的方法:
gunzip -c inputfile.gz |
awk '/CAPTURE/{capt=1} capt==1{a[i++]=$0} /CAPTURE/{for(j=0;j<i;j++) print a[j]; i=0}'
答案 3 :(得分:0)
我不认为正则表达式会比双重扫描更快......
这是awk
解决方案(双重扫描)
$ awk '/pattern/ && NR==FNR {a[++f]=NR; next} a[1]<=FNR && FNR<=a[f]' file{,}
或者,如果您有关于模式在文件中出现位置的任何先验信息,您可以使用启发式方法,这些方法在这些特殊情况下会更快。
答案 4 :(得分:0)
这是另一个使用正则表达式的例子(缺点是,如果文件很大,它将占用大量内存)
import { AnimatorModule } from 'css-animator';
@NgModule({
declarations: [
MyApp,
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
HttpClientModule,
AppConfigModule,
IonicStorageModule.forRoot(),
AnimatorModule
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
],
providers: [
StatusBar,
SplashScreen,
NativeStorage,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
]
})
或使用一个班轮:
#!/usr/bin/perl
{
local $/ = undef;
open FILE, $ARGV[0] or die "Couldn't open file: $!";
binmode FILE;
$string = <FILE>;
close FILE;
}
print $1 if $string =~ /([^\n]+(CAPTURE).*\2.*?)\n/s;
结果:
cat file.tmp | perl -ne '$/=undef; print $1 if <STDIN> =~ /([^\n]+(CAPTURE).*\2.*?)\n/s'
答案 5 :(得分:0)
这可能适合你(GNU sed):
sed '/CAPTURE/!d;:a;n;:b;//ba;$d;N;bb' file
删除所有行,直到第一行包含所需的字符串。打印包含所需字符串的行。用下一行替换模式空间。如果此行包含所需的字符串,请重复前两个句子。如果它是文件的最后一行,请删除模式空间。否则,追加下一行并重复前三句。
研究了用于haukex基准测试的测试文件后,似乎sed不是提取此文件的工具。使用csplit,grep和sed的混合物提供了一个相当快速的解决方案如下:
lines=$(grep -nTA1 --no-group-separator CAPTURE oldFile |
sed '1s/\t.*//;1h;$!d;s/\t.*//;H;x;s/\n/ /')
csplit -s oldFile $lines && rm xx0{0,2} && mv xx01 newFile
将原始文件拆分为三个文件。第一次出现CAPTURE
之前的文件,从第一个CAPTURE
到最后一个CAPTURE
的文件以及包含其余文件的文件。第一个和第三个文件被丢弃,第二个文件被重命名。
csplit
可以使用行号来拆分原始文件。 grep
在过滤模式方面非常快,可以返回与CAPTURE
和以下上下文行匹配的所有模式的行号。 sed
可以将grep
的结果操作为两个提供给csplit
命令的行号。
当针对测试文件运行时(如上所述),我得到大约10秒的时间。
答案 6 :(得分:0)
在发布这个问题时,我遇到的问题是我有几个巨大的gzip压缩日志文件由java应用程序生成。 日志行具有以下格式:
[Timestamp] (AppName) {EventId} [INFO]: Log text...
[Timestamp] (AppName) {EventId} [EXCEPTION]: Log text...
at com.application.class(Class.java:154)
caused by......
[Timestamp] (AppName) {EventId} [LogLevel]: Log text...
给定EventId
,我需要从这些文件中提取与事件对应的所有行。由于异常行可以是任意长度且不包含EventId
,因此问题变得无法解决,因为EventId
只有一个微不足道的grep。
不幸的是,我忘了考虑边缘情况,EventId
的最后一个日志行可能是例外,这里发布的答案不会打印stacktrace行。然而,修改haukex的解决方案并不难以涵盖这些案例:
#!/usr/bin/env perl
use warnings;
use strict;
my $first=1;
my @buf;
while ( my $line = <> ) {
push @buf, $line unless $first;
if ( $line=~/EventId/ or ($first==0 and $line!~/\(AppName\)/)) {
if ($first) {
@buf = ($line);
$first = 0;
}
print @buf;
@buf = ();
}
else {
$first = 1;
}
}
我仍然想知道是否可以修改更快的解决方案(主要是沃尔特的sed解决方案或haukex的内存perl解决方案)来做同样的事情。