slugman
slugman

Reputation: 33

Perl: load contents of string into array

I have a simple question I was hoping you guys can help shed light on. I'm steadily learning perl.

Say I have a very large string, for example take the output of:

our $z = `du -B MB /home`

This will produce a string like the following:

1MB     /home/debug/Music
1MB     /home/debug/Downloads
20MB    /home/debug
20MB    /home/

What I would like to know is, how do I go about loading this string into an array with two columns, and n rows (where n is the number of lines in the du output)?

I was trying something like the following:

my $z1 = `du -B MB /home | tail -4`;
my @c0 = split (/n/, $z1);
my $z2 = join (/\t/, @c0);
my @c2=split(/\t/, $z2);
print @c2;

Which produces the following output:

1MB/home/debug/Music1MB/home/debug/Downloads20MB/home/debug20MB/home

I suppose I can use the substitution function s///g to substitue the directories for null values, and set the SPACE values to one array, and null the space values and set that to a second array, and can set 1 array as keys to the other.

Does anyone have any suggestions as to the best way to approach this?

Any help is appreciated.

Thanks,

Diego

Upvotes: 1

Views: 834

Answers (4)

Mark Nodine
Mark Nodine

Reputation: 163

I'm honestly not sure what you're trying to accomplish. If you simply want to have an array with n elements, each of which is a string with two columns in it, you need look no farther than

my @z1 = `du -B MB /home | tail -4`;

For example, the third line of your file could be accessed (remember perl arrays are 0-based):

print $z1[2];

producing output

20MB    /home/debug

More useful would be to capture each directory's size in a hash:

my %dir2size;
foreach (@z1) {
    my @line = split /\s+/;
    $dir2size{$line[1]} = $line[0];
}
foreach my $key (sort keys %dir2size) {
    print "$key: $dir2size{$key}\n";
}

which produces the output

/home/: 20MB
/home/debug: 20MB
/home/debug/Downloads: 1MB
/home/debug/Music: 1MB

Upvotes: 0

slugman
slugman

Reputation: 33

I'm sure you perl veterans won't like this solution much, but I basically resolved to my nix roots. I was having trouble with this earlier in a for loop, but I realized I can utilize pipes to be evaluated via the shell, so long as the answer is stored in a string.

my $z1; my $z2;

$z1 = `du -B MB /home | cut -f1`
$z2 = `du -B MB /home | cut -f2`

my @a1; my @a2;

@a1 = split("\n", $z1);
@a2 = split("\n", $z2);

Array @a1 holds values from first string, @a2 holds values from 2nd string.

My question to you guys is, is there a perl equivelent to the unix 'cut' utility? I.e. where I can split a strings output to the first tab-delimited field? This is a problem I'll have to explore.

Diego

Upvotes: 0

dirkgently
dirkgently

Reputation: 111120

You can probably try and store them in a hash as follows:

#!/usr/bin/perl

use strict;
use warnings;

my $data = '1MB /home/work 4MB /user/bin';
my %values = split(' ', $data);
foreach my $k (keys %values) {
    print "$k: $values{$k}\n";
}
exit 0;

Note that ' ' as the first argument of split will match any whitespace character (so we make the most of it). The output for the above should be something like:

1MB: /home/work
4MB: /user/bin

You will have to work the original data into $data and check if a hash works for you.

Upvotes: 1

user993553
user993553

Reputation: 1077

#!/usr/bin/perl;
my $z= `du -h -d 1 /home/*`;
my @array  = split("\n",$z);
foreach my $ar(@array) {
my @ar = split("\t",$ar);
$ar = \@ar;
}

foreach my $entry(@array) {
print $entry->[0];
print $entry->[1];

}

Upvotes: 1

Related Questions