Perl 从制表符分隔的文件访问数据

Perl 从制表符分隔的文件访问数据,perl,Perl,例如,我有一个以制表符分隔的文件 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 我想输入这个

例如,我有一个以制表符分隔的文件

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

这里有一种方法可以获得您想要的输出,给定您的输入

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
使用警告;
严格使用;
我的%姓名;
而(){
下一个if/^ID/;
我的($first,$last)=(分割)[1..2];
$last=~s/,/;
先推@{$names{$last}},$first;
}
为@{$names{rodes}打印“$\urodes\n”;
__资料__
ID名称家庭标签效应
001约翰·布莱克阳性
002密歇根州凯特·罗德斯阳性
003 Aaron Sunders负片
004雪莉·罗兹底片
005德克斯特破甲阳性
#/usr/bin/perl
严格使用;
使用警告;
我的%db;
开放式(F,'1.pl.tst');
我的$find=“凯特”;
while()
{
咀嚼;
如果(/^(\d+[\t\]+(\w+[\t\]+([^\t\]+)[\t\]+(\w+)$/)
{
$db{$1}{'name'}=$2;
$db{$1}{'family'}=[split(',',$3)];
$db{$1}{'effect'}=$4;
}
}
我的@family={name2family($find)};
foreach(@family)
{
家庭名称(美元);
}
子名称2家族
{
我的$name=shift;
foreach(键%db)
{
if($db{${'name'}eq$name)
{
返回$db{${'family'};
}
}
}
子家族名称
{
我的$family=shift;
foreach my$k(密钥%db)
{
foreach(@{$db{$k}{'family'}})
{
如果($\uEQ$系列)
{
打印$db{$k}{'name'}.\t\t.$\n;
}
}
}
}

我不清楚
FAMILYTAG
列中的多个名字表明了什么,但我把它们放在一起,假设它们是其他姓氏

使用严格;
使用警告;
我的%姓名;
我的家庭;
而(){
下一步除非/^\d/;
我的($id,$name,$familytag,$effect)=split/\t/;
对于我的$tag(拆分/,/,$familytag){
推送@{$names{$name}},$tag;
push@{$families{$tag}},$name;
}
}
而(){
打印“\n名称:”;
chomp(我的$name=);
除非$name=~/\S/;
打印“\n”;
if(my$tags=$names{$name}){
对于我的$tag(@$tags){
我的$names=$families{$tag};
下一步除非@$names>1;
printf“%s%s\n”,@$名称的$标记;
}
}
否则{
警告qq(未找到名称“$name”);
}
}
__资料__
ID名称家庭标签效应
001约翰·布莱克阳性
002密歇根州凯特·罗德斯阳性
003 Aaron Sunders负片
004雪莉·罗兹底片
005德克斯特破甲,听好了
输出

E:\Perl\source>ff.pl
姓名:凯特
凯特·罗德斯
雪莉·罗德斯
姓名:亚伦
亚伦桑德斯
德克斯特破甲
姓名:迈克
在E:\Perl\source\ff.pl第31行第3行找不到名称“Mike”。
姓名:德克斯特
亚伦桑德斯
德克斯特破甲
可以被告知使用不同的分隔符<代码>“\t”在这种情况下

use Text::CSV;

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

然后使用
$tsv
对象,类似于该模块示例中的
$csv
对象。

嗨,toolic,我看到了..我也问了一个问题:)我想知道的是,这只是匹配所有Rhodes条目?脚本应该在Kate中读取,但我不确定它是否在这样做?一些提示:您应该始终使用
use warnings
,并检查
open
调用的返回值
split
s的第一个参数是正则表达式,
/,/
,而不是字符串,。您不需要转义字符类括号内的空格
[\t]
chomp
是多余的,因为正则表达式中的
$
包含可能的尾随换行符。使用哈希
%db
的方法相当于使用数组。使用警告会给出错误,在使用“严格引用”时不能将字符串用作数组引用。脚本运行正常,记住TLP的指针。但是我没有得到任何输出。我尝试将其输出到txt文件,但它仍然为空。使用制表符分隔的文件的主要原因是,字段本身可以包含空格。您的正则表达式应该只使用
\t
,而不是
[\t\]
。更好的是,只需使用
split/\t/
@TLP,我在'-w'或'-use-warnings'上没有警告。我知道,这就是为什么我说你应该总是使用警告。我只是在评论你的代码。你的问题应该包括如何处理第三列中的mulltiple逗号分隔值。此外,你在PerlMonks上的问题版本(顺便说一句,在多个论坛上同时问同一个问题是不礼貌的)在密歇根州罗兹的
中有一个空白。你必须准确、准确地解释你的问题,否则你得到的答案将无法解决真正的问题。
while()
在最近的问题上巧妙地使用。:)@TLP:当我需要一个不确定循环时,我在编写
while(){…}
while(1){…}
{…redo;}
之间摇摆不定。
use Text::CSV;

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