Perl使用字符串

时间:2017-07-21 09:09:50

标签: perl

朋友需要帮助。关注我的INPUT TEXT FILE

Andrew   UK
Cindy    China
Rupa     India
Gordon   Australia
Peter    New Zealand

将记录存在于目录中时,将上述内容转换为哈希并写回文件。我试过跟随(它不起作用)。

#!/usr/perl/5.14.1/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %hash = ();
my $file = ".../input_and_output.txt";
my $people;
my $country;

open (my $fh, "<", $file) or die "Can't open the file $file: ";
my $line;
while (my $line =<$fh>) {
  my ($people) = split("", $line);
  $hash{$people} = 1;
}


foreach my $people (sort keys %hash) {

  my @country = $people;
  foreach my $c (@country) {
    my $c_folder = `country/test1_testdata/17.26.6/$c/`;   

    if (-d $cad_root){
      print "Exit\n";
    } else {
      print "NA\n";
    }
 }

2 个答案:

答案 0 :(得分:3)

这是主要问题:

my ($people) = split("", $line);

您正在使用空字符串进行拆分,并且您将返回值分配给单个变量(最终将以每行的第一个字符结束)。

相反,您应该在split' 'a special pattern的单个空格字符):

  

作为另一种特殊情况,...当PATTERN被省略或由单个空格字符组成的字符串(例如' '"\x20",而不是/ /)时。在这种情况下,EXPR中的任何前导空格都会在拆分发生之前被删除,而PATTERN则被视为/\s+/;特别是,这意味着任何连续的空格(不只是一个空格字符)都被用作分隔符。

限制返回的字段数,以确保包含空格的国家/地区名称的完整性:

#!/usr/bin/env perl

use strict;
use warnings;

my @people;

while (my $line = <DATA>) {
    $line =~ /\S/ or next;
    $line =~ s/\s+\z//;
    push @people, [ split ' ', $line, 2 ];
}

use YAML::XS;
print Dump \@people;

__DATA__
Andrew   UK
Cindy    China
Rupa     India
Gordon   Australia
Peter    New Zealand

将条目添加到数组中以便1)保留输入顺序; 2)两个同名但来自不同国家的人不会导致一个条目丢失。

如果订单不重要,您可以在每个条目的数组引用中使用键入国家/地区名称的哈希值和人名。现在,我将承担订单问题(如果你付出更多努力来制定一个明确的问题,它会帮助我们。)

现在有一个选项是浏览人 - 国家/地区对列表,并打印目录country/test1_testdata/17.26.6/$c/所存在的所有对(顺便提一下,在您的代码中)

my $c_folder = `country/test1_testdata/17.26.6/$c/`;

那将尝试执行一个名为country/test1_testdata/17.26.6/$c/的程序,如果它产生任何结果,则将其输出保存在$c_folder中。故事的道德:在编程中,精确性很重要。仅仅因为`看起来像',这并不意味着你可以用一个来表示另一个。)

鉴于你的问题集中在哈希上,我使用了一系列对匿名哈希的引用来存储下面代码中的人 - 国家对列表。我缓存查找结果以减少您需要点击磁盘的次数。

#!/usr/bin/env perl

use strict;
use warnings;

@ARGV == 2 ? run( @ARGV )
      : die_usage()
;

sub run {
    my $people_data_file = shift;
    my $country_files_location = shift;

    open my $in, '<', $people_data_file
        or die "Failed to open '$people_data_file': $!";

    my @people;
    my %countries;

    while (my $line = <$in>) {
        next unless $line =~ /\S/; # ignore lines consisting of blanks
        $line =~ s/\s+\z//;# remove all trailing whitespace
        my ($name, $country) = split ' ', $line, 2;
        push @people, { name => $name, country => $country };
        $countries{ $country } = undef;
    }

    # At this point, @people has a list of person-country pairs
    # We are going to use %countries to reduce the number of
    # times we need to check the existence of a given directory,
    # assuming that the directory tree is stable while this program
    # is running.

    PEOPLE:
    for my $person ( @people ) {
        my $country = $person->{country};
        if ($countries{ $country }) {
            print join("\t", $person->{name}, $country), "\n";
        }
        elsif (-d "$country_files_location/$country/") {
            $countries{ $country } = 1;
            redo PEOPLE;
        }
    }
}

sub die_usage {
    die "Need data file name and country files location\n";
}

现在,这方面有很多变化,这就是为什么 制定一个清晰简洁的问题非常重要,以便人们试图帮助你回答<强烈> 你的 具体问题,而不是每个人在他们看到问题时提出他/她自己的问题解决方案。例如,人们也可以这样做:

#!/usr/bin/env perl

use strict;
use warnings;

@ARGV == 2 ? run( @ARGV )
      : die_usage()
;

sub run {
    my $people_data_file = shift;
    my $country_files_location = shift;

    open my $in, '<', $people_data_file
        or die "Failed to open '$people_data_file': $!";

    my %countries;

    while (my $line = <$in>) {
        next unless $line =~ /\S/; # ignore lines consisting of blanks
        $line =~ s/\s+\z//;# remove all trailing whitespace
        my ($name, $country) = split ' ', $line, 2;
        push @{ $countries{$country} }, $name;
    }

    for my $country (keys %countries) {
        -d "$country_files_location/$country"
            or delete $countries{ $country };
    }

    # At this point, %countries maps each country for which
    # we have a data file to a list of people. We can then
    # print those quite simply so long as we don't care about
    # replicating the original order of lines from the original
    # data file. People's names will still be sorted in order
    # of appearance in the original data file for each country.

    while (my ($country, $people) = each %countries) {
        for my $person ( @$people) {
            print join("\t", $person, $country), "\n";
        }
    }
}


sub die_usage {
    die "Need data file name and country files location\n";
}

答案 1 :(得分:-1)

如果你想要的是哈希中的名字计数器,那么我找到了你,伙计! 我不会尝试其余代码,因为您正在检查记录文件夹 我无法访问,所以我无法解决任何问题。

我看到你的一个问题。看看这个:

#!/usr/bin/env perl
use strict;
use warnings;  
use feature 'say'; # Really like using say instead of print because no need for newline. 

my $file = 'input_file.txt';
my $fh; # A filehandle. 

my %hash;
my $people;
my $country;
my $line;  
unless(open($fh, '<', $file)){die "Could not open file $_ because $!"}

while($line = <$fh>)
{
($people, $country) = split(/\s{2,}/, $line); # splitting on at least two spaces

say "$people \t $country"; # Just printing out the coolumns in the file or people and Country.

$hash{$people}++; # Just counting all the people in the hash.
                    # Seeing how many unique names there are, like is there more than one Cindy, etc ...?     
}

say "\nNow I'm just sorting the hash of people by names.";

foreach(sort{$a cmp $b} keys %hash)
{
say "$_ => $hash{$_}"; # Based on your file. The counter is at 1 because nobody has the same names. 
}

这是输出。正如你所看到的,我通过分割至少两个空格来解决问题,因此国名不会被删除。

Andrew   UK

Cindy    China

Rupa     India

Gordon   Australia

Peter    New Zealand

Andrew   United States

Now I'm just sorting the hash of people by names.
Andrew => 2
Cindy => 1
Gordon => 1
Peter => 1
Rupa => 1

我在文件中添加了另一个Andrew。这个安德鲁来自美国 如你看到的。我看到你的一个问题。看看这个:

my ($people) = split("", $line);

您正在拆分字符,因为这些引号之间没有空格。 如果你现在看一下这个变化,你就会分裂至少一个空间。

 my ($people) = split(" ", $line);