我的脚本的输入是这个文件,其中包含如下数据。
A food 75
B car 136
A car 69
A house 179
B food 75
C car 136
C food 85
对于第二列的每个不同值,我想打印第三列中的数字不同的任何行。
示例输出
C food 85
A car 69
这是我的Perl代码。
#! /usr/local/bin/perl
use strict;
use warning;
my %data = ();
open FILE, '<', 'data.txt' or die $!;
while ( <FILE> ) {
chomp;
$data{$1} = $2 while /\s*(\S+),(\S+)/g;
}
close FILE;
print $_, '-', $data{$_}, $/ for keys %data;
我可以打印哈希键和值,但无法获得所需的输出。
有关如何使用Perl执行此操作的任何指示?
答案 0 :(得分:1)
据我所知,你需要一个列出所有行的列表,其中有一个&#34;奇怪的一行&#34;具有相同的项目类型和第三列中与其他所有
不同的数字我认为这就是你需要的
它将所有数据读入散列%data
,因此$data{$type}{$n}
是使用该对象类型和数字的所有数据行的(引用)数组
然后再次扫描哈希,查找并打印所有只有一行的给定类型/数字和的实例,其中有相同对象类型的其他值(否则它会是唯一的条目而不是&#34;奇怪的一个&#34;)
use strict;
use warnings 'all';
use autodie;
my %data;
open my $fh, '<', 'data.txt';
while ( <$fh> ) {
my ( $label, $type, $n) = split;
push @{ $data{$type}{$n} }, $_;
}
for my $type ( keys %data ) {
my $items = $data{$type};
next unless keys %$items > 1;
for my $n ( keys %$items ) {
print $items->{$n}[0] if @{ $items->{$n} } == 1;
}
}
C food 85
A car 69
请注意,如果输入类似于
,则可能会为给定的对象类型打印多行B car 22
A car 33
B car 136
C car 136
这有两个&#34;奇怪的&#34;对于给定的对象类型只出现一次,因此将打印B car 22
和A car 33
答案 1 :(得分:0)
以下是指示:
首先,在输出之前,你需要记住某处的线条 其次,您需要根据您设置的规则丢弃以前记住的对象线 在您的情况下,规则是在对象的编号与先前记住的编号不同时丢弃 这两项任务都可以使用hash完成。
对于每一行:
my ($letter, $object, $number)=split /\s+/, $line;
if (!defined($hash{$object}) || $hash{$object}[0]!=$number) {
$hash{$object}=[$number, $line];
}
第三,您需要输出哈希:
for my $object(keys %hash) {
print $hash{$object}[1];
}
但是存在一个问题:哈希是一种无序结构,它不会按照你把它们放入哈希的顺序返回它的键。
所以,第四个:您需要为哈希数据添加排序,这可以像这样完成:
$hash{$object}=[$number,$line,$.]; # $. is the row number over all the input files or STDIN, we use it for sorting
在输出部分中,您使用存储的行号进行排序
(有关$a
,$b
变量)的详细信息,请参阅sort:
for my $object(sort { $hash{$a}[2]<=>$hash{$b}[2] } keys %hash) {
print $hash{$object}[1];
}
关于评论
我确信我的代码不包含任何错误 如果我们在一些高级用户编辑之前查看问题,它会说:
[举]
现在,如果数字列(第三个)具有不同的值(第二列中的位置匹配)...然后仅打印不匹配的数字行。例如..
食物75
B车136
一辆车69
房子179
B食物75
B车136
C食物85
示例输出(由于数字列不匹配)
C食物85
[/ cite]
我只能将print only the mismatched number line
解释为:打印数字更改的对象的最后一行。这显然符合OP提供的示例。
即便如此,在我的回答中,我通过声明根据OP想要的任何规则完成省略行来解决了误解的可能性。
在下面我说明了当时在我看来是什么规则
我认为它很好地解决了OP问题,因为毕竟, OP需要指针。
现在我的回答是批评的,因为它与编辑的(很久以后而不是OP)要求不匹配。
我不同意。
关于空格:指定分割的/\s+/
在这里不是错误,尽管有一些评论试图断言。
虽然我同意" "
对于拆分很常见,但我不同意在很多情况下必须使用" "
而不是/\s+/
。
/\s+/
是一个正则表达式,它是拆分的常规参数,而" "
是速记,实际上掩盖了含义。
有了这个,我决定在我的示例中使用显式split /\s+/, $line
,而不仅仅是split " ", $line
或仅split
来显示perl的内部工作。
我认为对任何一个新人都很重要。
使用/\s+/
是完全可以的,但是如果您希望在数据中有前导空格,请务必小心,请咨询perldoc -f split
并确定/\s+/
是否符合您的需求。