我需要将所有匹配的组推送到一个数组中。
#!/usr/bin/perl
use strict;
open (FILE, "/home/user/name") || die $!;
my @lines = <FILE>;
close (FILE);
open (FH, ">>/home/user/new") || die $!;
foreach $_(@lines){
if ($_ =~ /AB_(.+)_(.+)_(.+)_(.+)_(.+)_(.+)_(.+)_W.+txt/){
print FH "$1 $2 $3 $4 $5 $6 $7\n"; #needs to be first element of array
}
elsif ($_ =~ /CD_(.+)_(.+)_(.+)_(.+)_(.+)_(.+)_W.+txt/){
print FH "$1 $2 $3 $4 $5 $6\n"; #needs to be second element of array
}
}close (FH);
_ INPUT _
AB_ first--2-45_ Name_ is34_ correct_ OR_ not_W3478.txt
CD_ second_ input_ 89-is_ diffErnt_ 76-from_Wfirst6.txt
我没有将匹配的组写入FILE,而是将它们推送到数组中。我想不出push
以外的任何其他命令,但是这个函数不接受多个参数。做同样的最好方法是什么?将匹配的组推入数组后,输出应如下所示。
_ OUTPUT _
$array[0] = first--2-45 Name is34 correct OR not
$array[1] = second input 89-is diffErnt 76-from
答案 0 :(得分:4)
对push
使用的print
使用相同的参数:双引号中的字符串。
push @array, "$1 $2 $3 $4 $5 $6 $7";
答案 1 :(得分:3)
查看perldoc -f grep,它会返回列表中符合某些条件的所有元素的列表。
顺便说一下,push
确实会占用多个参数:请参阅perldoc -f push。
push @matches, grep { /your regex here/ } @lines;
你没有包含导致这个的代码..但有些奇怪,例如使用$_
作为函数调用。你确定要这么做吗?
答案 2 :(得分:1)
如果您使用的是Perl 5.10.1或更高版本,我就会这样写它。
#!/usr/bin/perl
use strict;
use warnings;
use 5.10.1; # or use 5.010;
use autodie;
my @lines = do{
# don't need to check for errors, because of autodie
open( my $file, '<', '/home/user/name' );
grep {chomp} <$file>;
# $file is automatically closed
};
# use 3 arg form of open
open( my $file, '>>', '/home/user/new' );
my @matches;
for( @lines ){
if( /(?:AB|CD)( (?:_[^_]+)+ )_W .+ txt/x ){
my @match = "$1" =~ /_([^_]+)/g;
say {$file} "@match";
push @matches, \@match;
# or
# push @matches, [ "$1" =~ /_([^_]+)/g ];
# if you don't need to print it in this loop.
}
}
close $file;
这对输入有点宽容,但正则表达式应该比原版更“正确”。
答案 3 :(得分:0)
请记住,列表上下文中的捕获匹配会返回捕获的字段(如果有):
#!/usr/bin/perl
use strict; use warnings;
my $file = '/home/user/name';
open my $in, '<', $file
or die "Cannot open '$file': $!";
my @matched;
while ( <$in> ) {
my @fields;
if (@fields = /AB_(.+)_(.+)_(.+)_(.+)_(.+)_(.+)_(.+)_W.+txt/
or @fields = /CD_(.+)_(.+)_(.+)_(.+)_(.+)_(.+)_W.+txt/)
{
push @matched, "@fields";
}
}
use Data::Dumper;
print Dumper \@matched;
当然,您也可以
push @matched, \@fields;
取决于您打算如何处理比赛。
答案 4 :(得分:0)
我想知道使用push
和巨型正则表达式是否真的是正确的方法。
OP表示他希望在索引0处以AB开头的行和在索引1处使用CD的行。 此外,那些正则表达式看起来像是一个由内而外的分裂给我。
在下面的代码中,我添加了一些教学评论,指出为什么我的做法与OP以及此处提供的其他解决方案不同。
#!/usr/bin/perl
use strict;
use warnings; # best use warnings too. strict doesn't catch everything
my $filename = "/home/user/name";
# Using 3 argument open addresses some security issues with 2 arg open.
# Lexical filehandles are better than global filehandles, they prevent
# most accidental filehandle name colisions, among other advantages.
# Low precedence or operator helps prevent incorrect binding of die
# with open's args
# Expanded error message is more helpful
open( my $inh, '<', $filename )
or die "Error opening input file '$filename': $!";
my @file_data;
# Process file with a while loop.
# This is VERY important when dealing with large files.
# for will read the whole file into RAM.
# for/foreach is fine for small files.
while( my $line = <$inh> ) {
chmop $line;
# Simple regex captures the data type indicator and the data.
if( $line =~ /(AB|CD)_(.*)_W.+txt/ ) {
# Based on the type indicator we set variables
# used for validation and data access.
my( $index, $required_fields ) = $1 eq 'AB' ? ( 0, 7 )
: $1 eq 'CD' ? ( 1, 6 )
: ();
next unless defined $index;
# Why use a complex regex when a simple split will do the same job?
my @matches = split /_/, $2;
# Here we validate the field count, since split won't check that for us.
unless( @matches == $required_fields ) {
warn "Incorrect field count found in line '$line'\n";
next;
}
# Warn if we have already seen a line with the same data type.
if( defined $file_data[$index] ) {
warn "Overwriting data at index $index: '@{$file[$index]}'\n";
}
# Store the data at the appropriate index.
$file_data[$index] = \@matches;
}
else {
warn "Found non-conformant line: $line\n";
}
}
预先警告,我只需将其输入浏览器窗口即可。因此,虽然代码应该是正确的,但可能存在错别字或错过的分号潜伏 - 它未经测试,使用它自负。