将行后跟匹配模式的行打印到文件 A,如果不匹配则打印到文件 B
Print lines followed by a line matching a pattern, to file A, if no match then print to file B
我正在尝试编写一个 Perl 脚本来解析文件并根据匹配条件分离其内容。示例文件(例如 test.txt)看起来像这样:
command something something keyword something something
filepath1
filepath2
command something something something something
filepath3
filepath4
filepath5
脚本的输出将是两个基于脚本输入文件名称的文件,test.keyword 和 test.nomatch。
test.keyword 会是这样的:
command something something keyword something something
filepath1
filepath2
test.nomatch 会是这样的:
command something something something something
filepath3
filepath4
filepath5
我曾尝试寻找实现此目标的方法,但找不到对我有帮助的方法。
这是我的脚本中唯一剩下的部分,现在让我发疯了。是的,我不是 Perl 专家。 :(
以下是我目前正在等待黄金循环条件的骨架:
#!/usr/bin/perl -a
my $fh = shift or die "No file passed as argument for splitting!\n";
open( infile, "<$fh" ) or die $!;
open( vef_output, ">$fh.vef" ) or die $!;
open( svf_output, ">$fh.svf" ) or die $!;
$mode = 0; #0 for vef and 1 for svf
while ( my $line = <$infile> ) {
if ( $line =~ /SOME_LIBRARY_OPTIONS/ ) {
if ( $line =~ /\-sv/ ) {
print {$svf_output} $line;
$mode = 1;
}
else {
print {$vef_output} $line;
$mode = 0;
}
next;
}
if ( $mode eq 0 ) {
print {$vef_output} $line;
next;
}
else {
print {$svf_output} $line;
next;
}
}
close($vef_output);
close($svf_output);
close($file);
虽然您的代码逻辑是正确的,您肯定会自己发现一些拼写错误,但我建议您修改一下您的 while 循环:
输入文件的每一行都必须打印一次(输入文件的开头可能除外)。与其设置 $mode
标志并对其进行测试,我宁愿切换输出 filehandle ,这会导致更清晰的代码:
#!/usr/bin/perl
use strict;
use warnings;
my $filename = shift or die "No file passed as argument for splitting!\n";
# add filename to error message - users will like it!
open( my $infile, "<", $filename ) or die "could not open $filename: $!";
open( my $vef_output, ">","$filename.vef" )
or die "could not open $filename.vef: $!";
open( my $svf_output, ">","$filename.svf" )
or die "could not open $filename.svf: $!";
my $active_out;
while ( my $line = <$infile> ) {
if ( $line =~ /SOME_LIBRARY_OPTIONS/ ) {
$active_out = $vef_output;
}
# depending on your regex this conditional can be nested or not...
if ( $line =~ /-sv/ ) {
$active_out = $svf_output;
}
next unless defined $active_out;
print $active_out $line;
}
close($vef_output);
close($svf_output);
close($infile);
代码可以写成更简单更易读的形式
#!/usr/bin/env perl
#
# vim: ai ts=4 sw=4
use strict;
use warnings;
my $fh = shift
or die "No file passed as argument for splitting!\n";
open my $in, '<', $fh or die $!;
open my $out_match, '>', $fh . 'vef' or die $!;
open my $out_nomatch, '>', $fh . 'svf' or die $!;
my $output_ready;
my $fh_out;
while ( <$in> ) {
$output_ready = 1 if /SOME_LIBRARY_OPTIONS/;
if( /-sv/ ) {
$fh_out = $out_match;
} else {
$fh_out = $out_nomatch;
}
print $fh_out, $_ if $output_ready;
}
close $in;
close $out_match;
close $out_nomatch;
我正在尝试编写一个 Perl 脚本来解析文件并根据匹配条件分离其内容。示例文件(例如 test.txt)看起来像这样:
command something something keyword something something
filepath1
filepath2
command something something something something
filepath3
filepath4
filepath5
脚本的输出将是两个基于脚本输入文件名称的文件,test.keyword 和 test.nomatch。
test.keyword 会是这样的:
command something something keyword something something
filepath1
filepath2
test.nomatch 会是这样的:
command something something something something
filepath3
filepath4
filepath5
我曾尝试寻找实现此目标的方法,但找不到对我有帮助的方法。 这是我的脚本中唯一剩下的部分,现在让我发疯了。是的,我不是 Perl 专家。 :(
以下是我目前正在等待黄金循环条件的骨架:
#!/usr/bin/perl -a
my $fh = shift or die "No file passed as argument for splitting!\n";
open( infile, "<$fh" ) or die $!;
open( vef_output, ">$fh.vef" ) or die $!;
open( svf_output, ">$fh.svf" ) or die $!;
$mode = 0; #0 for vef and 1 for svf
while ( my $line = <$infile> ) {
if ( $line =~ /SOME_LIBRARY_OPTIONS/ ) {
if ( $line =~ /\-sv/ ) {
print {$svf_output} $line;
$mode = 1;
}
else {
print {$vef_output} $line;
$mode = 0;
}
next;
}
if ( $mode eq 0 ) {
print {$vef_output} $line;
next;
}
else {
print {$svf_output} $line;
next;
}
}
close($vef_output);
close($svf_output);
close($file);
虽然您的代码逻辑是正确的,您肯定会自己发现一些拼写错误,但我建议您修改一下您的 while 循环:
输入文件的每一行都必须打印一次(输入文件的开头可能除外)。与其设置 $mode
标志并对其进行测试,我宁愿切换输出 filehandle ,这会导致更清晰的代码:
#!/usr/bin/perl
use strict;
use warnings;
my $filename = shift or die "No file passed as argument for splitting!\n";
# add filename to error message - users will like it!
open( my $infile, "<", $filename ) or die "could not open $filename: $!";
open( my $vef_output, ">","$filename.vef" )
or die "could not open $filename.vef: $!";
open( my $svf_output, ">","$filename.svf" )
or die "could not open $filename.svf: $!";
my $active_out;
while ( my $line = <$infile> ) {
if ( $line =~ /SOME_LIBRARY_OPTIONS/ ) {
$active_out = $vef_output;
}
# depending on your regex this conditional can be nested or not...
if ( $line =~ /-sv/ ) {
$active_out = $svf_output;
}
next unless defined $active_out;
print $active_out $line;
}
close($vef_output);
close($svf_output);
close($infile);
代码可以写成更简单更易读的形式
#!/usr/bin/env perl
#
# vim: ai ts=4 sw=4
use strict;
use warnings;
my $fh = shift
or die "No file passed as argument for splitting!\n";
open my $in, '<', $fh or die $!;
open my $out_match, '>', $fh . 'vef' or die $!;
open my $out_nomatch, '>', $fh . 'svf' or die $!;
my $output_ready;
my $fh_out;
while ( <$in> ) {
$output_ready = 1 if /SOME_LIBRARY_OPTIONS/;
if( /-sv/ ) {
$fh_out = $out_match;
} else {
$fh_out = $out_nomatch;
}
print $fh_out, $_ if $output_ready;
}
close $in;
close $out_match;
close $out_nomatch;