-1

たとえば、タブ区切りのファイルがあります

ID   NAME      FAMILYTAG     EFFECT
001  John      Black         Positive
002  Kate      Rhodes,Mich   Positive
003  Aaron     Sunders       Negative
004  Shirley   Rhodes        Negative
005  Dexter    Sunders,Hark  Positive

このファイル(実際にははるかに大きい)を入力して、たとえば名前を入力したいと思いますKate。スクリプトにそのファミリタグを認識させたい、つまり、スクリプトにが含まれていることを認識してからRhodes、他のファミリメンバーを出力しShirleyます。これを行う方法はありますか?出力ファイルは次のようになります。

Kate  Rhodes 
Shirley Rhodes
4

4 に答える 4

1

入力を考慮して、必要な出力を取得する1つの方法を次に示します...

use warnings;
use strict;

my %names;
while (<DATA>) {
    next if /^ID/;
    my ($first, $last) = (split)[1 .. 2];
    $last =~ s/,//;
    push @{ $names{$last} }, $first;
}
print "$_ Rhodes\n" for @{ $names{Rhodes} };

__DATA__
ID     NAME   FAMILYTAG   EFFECT
001  John      Black               Positive
002  Kate      Rhodes, Mich           Positive
003  Aaron   Sunders          Negative
004  Shirley  Rhodes          Negative
005  Dexter    Sunders        Positive

PerlMonks の回答からコピー

于 2012-04-27T16:07:03.570 に答える
1

列内の複数の名前が何をFAMILYTAG示しているかは明確ではありませんが、別の姓であると仮定してまとめました.

use strict;
use warnings;

my %names;
my %families;

while (<DATA>) {
  next unless /^\d/;
  my ($id, $name, $familytag, $effect) = split /\t/;
  for my $tag (split /,/, $familytag) {
    push @{ $names{$name} }, $tag;
    push @{ $families{$tag} }, $name;
  }
}

while () {

  print "\nName: ";
  chomp (my $name = <>);
  last unless $name =~ /\S/;
  print "\n";

  if (my $tags = $names{$name}) {
    for my $tag (@$tags) {
      my $names = $families{$tag};
      next unless @$names > 1;
      printf "%s %s\n", $_, $tag for @$names;
    }
  }
  else {
    warn qq(No name "$name" found);
  }
}


__DATA__
ID  NAME    FAMILYTAG   EFFECT
001 John    Black   Positive
002 Kate    Rhodes,Mich Positive
003 Aaron   Sunders Negative
004 Shirley Rhodes  Negative
005 Dexter  Sunders,Hark    Positive

出力

E:\Perl\source>ff.pl

Name: Kate

Kate Rhodes
Shirley Rhodes

Name: Aaron

Aaron Sunders
Dexter Sunders

Name: Mike

No name "Mike" found at E:\Perl\source\ff.pl line 31, <> line 3.

Name: Dexter

Aaron Sunders
Dexter Sunders
于 2012-04-27T22:25:56.550 に答える
0

Text::CSV別の区切り文字を使用するように指示できます。"\t"この場合。

use Text::CSV;

my $tsv = Text::CSV->new ( { sep_char => "\t" } );

次に、そのモジュールの例にある$tsvオブジェクトと同様にオブジェクトを使用します。$csv

于 2012-04-30T18:13:11.700 に答える
0
#!/usr/bin/perl

use strict;
use warnings;
my %db;

open (F,'1.pl.tst');

my $find="Kate";
while(<F>)
{
    chomp;
    if (/^(\d+)[\t\ ]+(\w+)[\t\ ]+([^\t\ ]+)[\t\ ]+(\w+)$/)
    {
        $db{$1}{'name'}=$2;
        $db{$1}{'family'}=[split(',',$3)];
        $db{$1}{'effect'}=$4;
    }
}

my @family=@{name2family($find)};
foreach (@family)
{
    family2name($_);
}

sub name2family
{
    my $name=shift;
    foreach (keys %db)
    {
        if ($db{$_}{'name'} eq $name)
        {
            return $db{$_}{'family'};
        }
    }
}

sub family2name
{
    my $family=shift;
    foreach my $k (keys %db)
    {
        foreach (@{$db{$k}{'family'}})
        {
            if ($_ eq $family)
            {
                print $db{$k}{'name'}."\t\t".$_."\n";
            }
        }
    }
}
于 2012-04-27T16:33:23.873 に答える