2013-03-20 34 views
-2

分隔我有一个看起来像提取的记录特定多行被管在Perl

NAME|JOHN|TOKYO|JPN 
AGE|32|M 
INFO|SINGLE|PROFESSIONAL|IT 
NAME|MARK|MANILA|PH 
AGE|37|M 
INFO|MARRIED|PROFESSIONAL|BPO 
NAME|SAMANTHA|SYDNEY|AUS 
AGE|37|F 
INFO|MARRIED|PROFESSIONAL|OFFSHORE 
NAME|LUKE|TOKYO|JPN 
AGE|27|M 
INFO|SINGLE|PROFESSIONAL|IT

我想国家的记录分开的文件。我已存储的每一行到数组变量@fields

my @fields = split(/\|/, $_); 

使得$fields[3]作为我的用于分选它的基础。我想它分成2个输出文本文件

输出文本文件1:

NAME|JOHN|TOKYO|JPN 
AGE|32|M 
INFO|SINGLE|PROFESSIONAL|IT 
NAME|LUKE|TOKYO|JPN 
AGE|27|M 
INFO|SINGLE|PROFESSIONAL|IT 

输出文本文件2

NAME|MARK|MANILA|PH 
AGE|37|M 
INFO|MARRIED|PROFESSIONAL|BPO 
NAME|SAMANTHA|SYDNEY|AUS 
AGE|37|F 
INFO|MARRIED|PROFESSIONAL|OFFSHORE 

把所有从JPN输出文本1 &非JPN国家输出文本文件2

这里的代码是什么试图解决

use strict; 
use warnings; 
use Data::Dumper; 
use Carp qw(croak); 

my @fields; 
my $tmp_var; 
my $count; 
; 
my ($line, $i); 

my $filename = 'data.txt'; 
open(my $input_fh, '<', $filename) or croak "Can't open $filename: $!"; 


open(OUTPUTA, ">", 'JPN.txt') or die "wsl_reformat.pl: could not open $ARGV[0]"; 
open(OUTPUTB, ">", 'Non-JPN.txt') or die "wsl_reformat.pl: could not open $ARGV[0]"; 

my $fh; 
while (<$input_fh>) { 

    chomp; 
    my @fields = split /\|/; 


    if ($fields[0] eq 'NAME') { 
    for ($i=1; $i < @fields; $i++) { 
     if ($fields[3] eq 'JPN') { 
      $fh = $_; 
      print OUTPUTA $fh; 
     } 
     else { 
      $fh = $_; 
      print OUTPUTB $fh; 
     } 
    } 

} 
} 

close(OUTPUTA); 
close(OUTPUTB) 

仍然没有运气就可以了:(

+0

对不起,我还需要15次我就可以投票前。 – Soncire 2013-03-21 00:06:17

回答

1

这里是我想池上是说的方式,但在此之前我从来没有尝试过这一点(虽然它给出了正确的结果)。

#!/usr/bin/perl 
use strict; 
use warnings; 

open my $jpn_fh, ">", 'o33.txt' or die $!; 
open my $other_fh, ">", 'o44.txt' or die $!; 

my $fh; 
while (<DATA>) { 
    if (/^NAME/) { 
     if (/JPN$/) { 
      $fh = $jpn_fh; 
     } 
     else { 
      $fh = $other_fh; 
     } 
    } 
    print $fh $_; 
} 

close $jpn_fh or die $!; 
close $other_fh or die $!; 

__DATA__ 
NAME|JOHN|TOKYO|JPN 
AGE|32|M 
INFO|SINGLE|PROFESSIONAL|IT 
NAME|MARK|MANILA|PH 
AGE|37|M 
INFO|MARRIED|PROFESSIONAL|BPO 
NAME|SAMANTHA|SYDNEY|AUS 
AGE|37|F 
INFO|MARRIED|PROFESSIONAL|OFFSHORE 
NAME|LUKE|TOKYO|JPN 
AGE|27|M 
INFO|SINGLE|PROFESSIONAL|IT 
+0

是的,这是解决我的问题 克里斯,你可以请在每一行写评论,所以我可以理解你的代码非常感谢你 – Soncire 2013-03-20 02:31:29

+0

如果你读过的行以NAME开头(/^NAME /),那么if同一行以JPN结尾(/ JPN $ /),将文件句柄设置为$ jpn,否则将其设置为$ other。然后下面的打印将它指向正确的文件。 – 2013-03-20 02:41:16

+0

感谢克里斯 我有一个子程序,消除空间和其他的东西 子_trim { \t我的$字=移位; \t if($ word){ \t \t $ word =〜s/\ A \ s + | \ s + \ z // g; \t \t $ word =〜s/\ s +// g; \t \t $ word =〜s/\ | \ s */\ |/g; \t \t $ word =〜s/\ s * \ |/\ |/g; \t \t $ word =〜s/\ $ \ s +/\ $/g; \t \t $ word =〜s/^ \ s + //; \t \t $字=〜S /“//克; \t} \t回$字; } 我怎么会嵌入到你的代码 – Soncire 2013-03-20 02:57:21

1

你没有说你需要哪方面的帮助,所以我假设它的未来与算法。这里有一个好的:

  1. 打开文件进行阅读。
  2. 打开JPN条目的文件。
  3. 打开非JPN条目的文件。
  4. 虽然不是eof,
    1. 阅读一条线。
    2. 解析该行。
    3. 如果它是一个记录的第一线,
      1. 如果使用者的国家是JPN,
        1. 设置当前文件句柄为JPN项文件句柄。
      2. 否则,
        1. 设置当前文件句柄到非JPN项的文件句柄。
    4. 将行打印到当前文件句柄。

my $jpn_qfn = '...'; 
my $other_qfn = '...'; 

open(my $jpn_fh, '>', $jpn_qfn) 
    or die("Can't create $jpn_qfn: $!\n"); 
open(my $other_fh, '>', $other_qfn) 
    or die("Can't create $other_qfn: $!\n"); 

my $fh; 
while (<>) { 
    chomp; 
    my @fields = split /\|/; 
    if ($fields[0] eq 'NAME') { 
     $fh = $fields[3] eq 'JPN' ? $jpn_fh : $other_fh; 
    } 

    say $fh $_; 
} 
+0

因为我是新来的perl 你能告诉我我将如何提取每3行 – Soncire 2013-03-20 01:51:00

+0

你不必;在记录的第一行更改要写入的文件(步骤4.3.1.1和4.3.2.1)会自动使接下来的两行到达正确的位置 – ysth 2013-03-20 02:16:37

+0

@Soncire,您在哪里可以看到“提取3行”我发布了什么? – ikegami 2013-03-20 03:55:32

0
#!/usr/bin/env perl 

use 5.012; 
use autodie; 
use strict; 
use warnings; 

# store per country output filehandles 
my %output; 

# since this is just an example, read from __DATA__ section 

while (my $line = <DATA>) { 
    # split the fields 
    my @cells = split /[|]/, $line; 

    # if first field is NAME, this is a new record 
    if ($cells[0] eq 'NAME') { 
     # get the country code, strip trailing whitespace 
     (my $country = $cells[3]) =~ s/\s+\z//; 

     # if we haven't created and output file for this 
     # country, yet, do so 
     unless (defined $output{$country}) { 
      open my $fh, '>', "$country.out"; 
      $output{$country} = $fh; 
     } 
     my $out = $output{$country}; 

     # output this and the next two lines to 
     # country specific output file 
     print $out $line, scalar <DATA>, scalar <DATA>; 
    } 
} 

close $_ for values %output; 

__DATA__ 
NAME|JOHN|TOKYO|JPN 
AGE|32|M 
INFO|SINGLE|PROFESSIONAL|IT 
NAME|MARK|MANILA|PH 
AGE|37|M 
INFO|MARRIED|PROFESSIONAL|BPO 
NAME|SAMANTHA|SYDNEY|AUS 
AGE|37|F 
INFO|MARRIED|PROFESSIONAL|OFFSHORE 
NAME|LUKE|TOKYO|JPN 
AGE|27|M 
INFO|SINGLE|PROFESSIONAL|IT 
0

感谢您的帮助堆 我能够在Perl解决了这个问题, 千恩万谢

#!/usr/local/bin/perl 

use strict; 
use warnings; 
use Data::Dumper; 
use Carp qw(croak); 

my @fields; 
my $tmp_var; 
my ($rec_type, $country); 

my $filename = 'data.txt'; 


open (my $input_fh, '<', $filename) or croak "Can't open $filename: $!"; 


open my $OUTPUTA, ">", 'o33.txt' or die $!; 
open my $OUTPUTB, ">", 'o44.txt' or die $!; 

my $Combline; 
while (<$input_fh>) { 

    $_ = _trim($_); 
    @fields = split (/\|/, $_); 
    $rec_type = $fields[0]; 
    $country = $fields[3]; 

     if ($rec_type eq 'NAME') {   
      if ($country eq 'JPN') {        
       *Combline = $OUTPUTA; 
      }   
      else {        
       *Combline = $OUTPUTB; 
      } 
     }  
    print Combline; 
} 

close $OUTPUTA or die $!; 
close $OUTPUTB or die $!; 

sub _trim { 
    my $word = shift; 
    if ($word) {  
     $word =~ s/\s*\|/\|/g;  #remove trailing spaces 
     $word =~ s/"//g;  #remove double quotes 
    } 
    return $word; 
}