Tom //name
Washington
account.txt //filename
Gary //NAME
New York
accountbalance.png //filename
Mary //name
New Jersey
Michelle //NAME
Larry //NAME
Charles //NAME
Washington
Real.cpp //FILENAME
.
.goes on(large file)
我想提取名称和相应的文件名。例如,Charles是使用real.cpp工作的人的名字....
我想我需要
面临的问题:我得到与其不对应的名称和文件名...(由于文本文件读取中没有一对一关系的不一致) 我希望名称是键和文件名作为值并将其存储在哈希中 如何解决这个......我很困惑。给我建议,请
答案 0 :(得分:1)
如果名称后面总是有//name
,文件名后面总是有//filename
,文件名前的名称就是与文件名关联的名称,这很简单:
#!/usr/bin/perl
use strict;
use warnings;
my $key;
my %name_to_filename;
while (<DATA>) {
#only pay attention to lines that have //name or //filename
#and save off the part before //name or //filename and which type it was
next unless my ($name, $type) = m{(.*?)\s+//(name|filename)}i;
if ($type =~ /^name$/i) {
$key = $name; #remember the last name seen
next;
}
$name_to_filename{$key} = $name;
}
use Data::Dumper;
print Dumper \%name_to_filename;
__DATA__
Tom //name
Washington
account.txt //filename
Gary //NAME
New York
accountbalance.png //filename
Mary //name
New Jersey
Michelle //NAME
Larry //NAME
Charles //NAME
Washington
Real.cpp //FILENAME
答案 1 :(得分:0)
有3个变量 LINE_1,LINE_2,Current_line。 对于前两行读取变量Line_1,Line_2被初始化。 现在读取第3行时检查它是否为File 如果是,则将其存储在散列哈希{filename} = name,city中。 如果不是,则将Line_2复制到Line_1,将Current_line复制到Line_2。 这个shuld发生在循环中直到读完整个文件
答案 2 :(得分:0)
因为您要将名称映射到文件名。数据显示您获得了一个列表 的名称,然后是文件名。因此,您需要存储密钥,直到 你知道你可以存储它们。
此外,由于你没有对州名说什么,我希望你想要 忽略那些。所以我们需要一种方法来区分它们。幸运的是,各州都是 一个定义良好的集合,可以放入查找表中。
然后,我们需要一种方法来区分名称和文件名,以及你展示的内容,我是 使用以下模式:至少一个单词字符,然后单个点, 然后至少有一个单词字符用于扩展。
这样会告诉我我们是否在文件行上,并且可以解析该值 待定名称。
@ARGV = '/path/to/file';
my %state_hash
= ( Alabama => 1, Alaska => 1, Arizona => 1, ...
, 'New Hampshire' => 1, ..., Wyoming => 1
);
my ( @pending_names, %file_for );
while ( <> ) {
# Extract non-spaces at the beginning of the line
# potentially separated with one-and-only-one space
my ( $name_or_file ) = m/^(?:\S+[ ]?)+)/;
next unless $name_or_file or exists $state_hash{ $name_or_file };
# if the extract value fits the file pattern
if ( $name_or_file =~ m/^\w+\.\w+$/ ) {
# store the name-file combination for each pending
$file_for{ $_ } = $name_or_file foreach @pending_names;
# they are not pending anymore, so clear them.
@pending_names = ();
}
else {
# store up pending names
push @pending_names, $name_or_file;
}
}
你没有要求处理的是,它是一个“大文件”,一个名字 可能会重演。如果一个名称不止一次重复,你就会破坏这个价值 你上次保存。
这可以通过push
补救 - 进入散列槽而不是简单地分配它。像这样:
push @{ $file_for{ $_ } }, $name_or_file foreach @pending_name;
答案 3 :(得分:0)
此版本使用名为%is_city
的哈希来跳过看起来像城市的行,并假设包含.
的名称是文件名。但这两种假设都很糟糕。例如,我的名字包含一个句号,像麦迪逊这样的名字可以是一个城市或一个人的名字。
#!/usr/bin/perl
use strict;
use warnings;
my %is_city = map { $_ => 1 } (
"Washington", "New York", "New Jersey",
);
my $key;
my %name_to_filename;
while (my $name = <DATA>) {
chomp $name;
next if $is_city{$name};
if ($name =~ /[.]/) {
$name_to_filename{$key} = $name;
next;
}
$key = $name;
}
use Data::Dumper;
print Dumper \%name_to_filename;
__DATA__
Tom
Washington
account.txt
Gary
New York
accountbalance.png
Mary
New Jersey
Michelle
Larry
Charles
Washington
Real.cpp
答案 4 :(得分:0)
假设所有文件名中都包含.
,并且该文件名是唯一的文件名。
同时假设城市和州的名单太大而无法获得整个清单。
#! /usr/bin/env perl
use strict;
use warnings;
my @state_city_or_person;
my %files;
while(<>){
chomp;
if( index($_,'.') >= 0 ){
push @{ $files{$_} }, @state_city_or_person;
@state_city_or_person = ();
}else{
push @state_city_or_person, $_;
}
}
use YAML;
print Dump \%files;
--- Real.cpp: - Mary - New Jersey - Michelle - Larry - Charles - Washington account.txt: - Tom - Washington accountbalance.png: - Gary - New York
您仍然需要通过并删除任何无关的数据,例如城市和州,但这可以帮助您将其转换为实际的可解析格式。
如果数据的某种结构开始,将会很有帮助。