Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
SynVisions
Jun 29, 2003

There are a lot of ways, this is how I usually do it:

code:
foreach my $processor (@{$Processors}) {
    foreach my $key (keys %{$processor}) {
            print "$key: $processor->{$key}\n";
    }
}
This is assuming that $Processors is what you're working with and is a reference to an array of hashes.

SynVisions fucked around with this message at 01:46 on Dec 8, 2010

Adbot
ADBOT LOVES YOU

syphon
Jan 1, 2001
That returned "Not a HASH reference at servers.pl line 76." (the 2nd line in your code snippet). I thought I had a good handle on referencing/dereferencing various data types, but this problem escapes me.

syphon fucked around with this message at 01:57 on Dec 8, 2010

SynVisions
Jun 29, 2003

Did you catch my edit?

I assumed from you referencing Dumper(@Processors) in your original post that is what you were working with, but later on you're using @{$Processors} which is dereferencing an array.

So I changed

code:
foreach my $processor (@Processors}) {
to

code:
foreach my $processor (@{$Processors}) {

syphon
Jan 1, 2001
The edit fixed it. Now that I have working code... I'll have to go back and try to comprehend what's going on! Thanks for your help!

I think the core of my problem was that I was initializing @Processors (an array) yet the place I got the data from was an array-ref. Is it possible that @Processors somehow came out as an array-ref, even though it looked like an array? Is it even possible to dereference an array-ref into an array if the original array-ref looks like an array to begin with?!?!

Crap, now i have a headache. I think I need to go stare out the window for a while! :)

syphon fucked around with this message at 01:59 on Dec 8, 2010

toadee
Aug 16, 2003

North American Turtle Boy Love Association

syphon posted:

The edit fixed it. Now that I have working code... I'll have to go back and try to comprehend what's going on! Thanks for your help!

What's happening is what you said initially. @Processors is indeed an array of anonymous hashes containing the info for each within. When you say 'for my $processor (@Processors)' you are looping through thay array assigning a reference to the anonymous hash in each element to $processor. From there you loop through all keys in %{$processor} (the dereferenced hash), and print the value for each key in that hash.

SynVisions
Jun 29, 2003

I don't know how you're being passed the data, but if you want you can dereference it on the spot so you can use @Processors.

e.g.

code:
my @Processors = @{GetData()};

Erasmus Darwin
Mar 6, 2001

syphon posted:

I think the core of my problem was that I was initializing @Processors (an array) yet the place I got the data from was an array-ref. Is it possible that @Processors somehow came out as an array-ref, even though it looked like an array?

@Processors must always be an array. What you've done is assigned a single element to it that's an array-ref. So it's an array containing an array containing hashes.

If you do 'print Dumper(\@Processors);' instead of 'print Dumper(@Processors);', you'll see it for what it is.

syphon
Jan 1, 2001
I've got a quick question. Does anyone know of a module to measure the duration of dates? For my application, I have a string that represents a server's LastBootTime and want a module to convert that into an Uptime. I poked around the DateTime stuff on CPAN but can't find something applicable.

For example, I want to convert "11/14/2010 8:01:56 AM" into something like "24 days, 7 hours, 44 minutes" (I don't care too much about the formatting of the output).

EDIT: Wow, an answer before I even finished editing my post to increase readability. Thanks!

syphon fucked around with this message at 00:46 on Dec 9, 2010

toadee
Aug 16, 2003

North American Turtle Boy Love Association

syphon posted:

I've got a quick question. Does anyone know of a module to measure the duration of dates? For my application, I have a string that represents a server's "LastBootTime" (e.g. "11/14/2010 8:01:56 AM") and want a module to convert that into an Uptime. I poked around the DateTime stuff on CPAN but can't find something applicable.

Date::Calc is awesome.

Roseo
Jun 1, 2000
Forum Veteran

toadee posted:

Date::Calc is awesome.

Ugh, ugh, ugh, no. Use DateTime's duration stuff. Off the cuff, it's something like:

code:
my $now = DateTime->now(time_zone => DateTime::TimeZone->new( name => 'local' ));
### parse the boot string into a DateTime object $boot

my $uptime = $now - $boot;
### $uptime is a DateTime::Duration object.
Edit: To expand on this, the problem you get into when you start poking around into the dozens of Date:: modules is that none of them deal with the same formats, so you have to constantly rejigger your data structures to do different calculations. DateTime does everything (and that's why it was created in the first place). Just learn its API.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
just use Date::Manip, it parses everything :q:

mister_gosh
May 24, 2002

Are there any considerations to make with this script on W7? It works fine on my XP machine but does not work in W7 on a particular machine. The permissions appear to be open for the user (I believe they are an admin, in fact):

code:
open(LOG, ">C:/helloworld.txt");
print LOG "hello world";
close LOG;

The Gate of Nanna
Sep 20, 2008

:c00l: My Editor :c00l:

mister_gosh posted:

Are there any considerations to make with this script on W7? It works fine on my XP machine but does not work in W7 on a particular machine. The permissions appear to be open for the user (I believe they are an admin, in fact):

code:
open(LOG, ">C:/helloworld.txt");
print LOG "hello world";
close LOG;

What distribution of Perl are you using for Windows? ActiveState? Strawberry?

Try this: (open's 2 vs 3 arg may be different on Windows)
code:
open(my $LOG, '>', 'C:/helloworld.txt') or die $!;
print {$LOG} "hello world";
close $LOG;

mister_gosh
May 24, 2002

The Gate of Nanna posted:

What distribution of Perl are you using for Windows? ActiveState? Strawberry?

Try this: (open's 2 vs 3 arg may be different on Windows)
code:
open(my $LOG, '>', 'C:/helloworld.txt') or die $!;
print {$LOG} "hello world";
close $LOG;

It is activestate 5.10.0

I'll have the user try that. Thanks!

Ninja Rope
Oct 22, 2005

Wee.

mister_gosh posted:

Are there any considerations to make with this script on W7? It works fine on my XP machine but does not work in W7 on a particular machine. The permissions appear to be open for the user (I believe they are an admin, in fact):

code:
open(LOG, ">C:/helloworld.txt");
print LOG "hello world";
close LOG;

Isn't that just Windows 7 keeping the user from writing to the root of the drive? It's not enough to be "an admin", you have to run the interpreter as "an admin", ie, via right-clicking it and saying "Run as administrator".

Alternately, make that open() || die $! so you at least get an error message?

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
typester is alive :woop:

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!

Otto Skorzeny posted:

typester is alive :woop:

Wait, this typester? http://twitter.com/typester

What made you think otherwise?

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
the infobot on irc hadn't seen him in 60 days (I was looking for him to see what was up with a patch to one of his modules that I'd submitted in October). I think I heard a while back that he was on vacation in Spain for a while. He responded to the bug report on RT by accepting the patch yesterday so I guess he's good to go now.

monsterland
Nov 11, 2003

How do I split a UNC path in format

"\\server\share\blah\..."

into two strings:

"server"

and

"\share\blah\..."

using a ONE-LINE regular expression? (not "split" or anything like that)

This is a specific assignment I am given at work, and I have a terrible time trying to learn it academically from "Programming PERL". I cannot bend the examples in "PERL Cookbook" into what I need, either. Same goes for googling. There's a learning curve, and I am being asked to skip half of it, looks like.

Anaconda Rifle
Mar 23, 2007

Yam Slacker
my ($server, $rest) = $string =~ /^\\\\([^\\]+)\\(.*)$/;

Edit: Though I don't know why you wouldn't want to use a 3 argument split after stripping off the first two characters:

my ($server, $rest) = split(/\\/, substr($string, 2), 2);

Second edit:

You wanted to keep the \ for the rest. Here are your new lines of code:

my ($server, $rest) = $string =~ /^\\\\([^\\]+)(\\.*)$/;

or

my ($server, $rest) = split(/(?=\\)/, substr($string, 2), 2);

Anaconda Rifle fucked around with this message at 21:50 on Dec 16, 2010

monsterland
Nov 11, 2003

Awesome, thanks! You sir are a gentleman and a scholar.

EVGA Longoria
Dec 25, 2005

Let's go exploring!

I've got an object - Champion - which contains an attribute - Powers - which is an arrayref.

I have a method - addPower - which takes this arrayref and adds an object - Power - to it.

I then have a method - listPowers - which takes this arrayref, cycles through it, and uses a method - name - on each entry in there.

I'm able to perform the first 2 parts fine. However, the listPowers part fails. Code and error below:

code:
sub listPowers {
    my $self = shift;
    my $powers = $self->powers();
    
    foreach my $power (@{$powers}) {;
        print $power->name();
    }
}
code:
Can't call method "name" without a package or object reference at ChampionsModule.pm line 54.
Can anyone tell me where I'm going wrong?

I'm using Moose, btw, which is what's generating the name() and powers() methods.

Roseo
Jun 1, 2000
Forum Veteran
Can you paste the full package?

Edit: and a dump of $self->powers(). Somewhere along the way you're trying to do a method on a non-object. What you say is correct, but something in your code isn't what you say it is. Mostly because "foreach my $power (@{$powers}) {;" would lead to a compailation error due to the stray semicolon.

Roseo fucked around with this message at 04:20 on Dec 22, 2010

EVGA Longoria
Dec 25, 2005

Let's go exploring!

Roseo posted:

Can you paste the full package?

Edit: and a dump of $self->powers(). Somewhere along the way you're trying to do a method on a non-object. What you say is correct, but something in your code isn't what you say it is. Mostly because "foreach my $power (@{$powers}) {;" would lead to a compailation error due to the stray semicolon.

Sorry, code was on my laptop. Posted:

http://pastebin.com/s8eJbf4i is the module. Calling lines are:

code:
$hero->addPower(name => 'Windwalker', const => '1', end => 2);

$hero->listPowers();
What exactly qualified a dump of the powers part? It shows up as a hash array when I print it out, and when I run REF on it it returns ARRAY.

The semicolon thing got put in at the end by accident last night, not sure why. It still has the issue without it.

Also, just hosed with recovery, it's seriously not that bad anymore, I was tired when I wrote that :(

EVGA Longoria fucked around with this message at 06:15 on Dec 23, 2010

welcome to hell
Jun 9, 2006
code:
sub addPower {
...
    my @powers = $self->powers();
...
}
code:
sub listPowers {
...
    my $powers = $self->powers();
...
}
powers is an array reference so addPower ends up working incorrectly.

Also, that extra semicolon wouldn't cause any problems. It would just be an empty statement.

Roseo
Jun 1, 2000
Forum Veteran
While the bug got pointed out,

Casao posted:

What exactly qualified a dump of the powers part? It shows up as a hash array when I print it out, and when I run REF on it it returns ARRAY.

code:
use Data::Dumper;
print Dumper $self->powers();
It helps debug why your data structures aren't working the way you think. for example, look at the difference between the two variables when running the below code:


code:
use Data::Dumper;

my @array = qw/foo bar baz/;
my $array_ref = [qw/foo bar baz/];
print Dumper @array;
print Dumper $array_ref;

Roseo
Jun 1, 2000
Forum Veteran
Oh, and think about this. You don't need intermediate scalars.

code:
sub addPower {
    my $self = shift;
    my %params = @_;

    $self->powers([@{$self->powers()}, Power->new(%params)]);
}
 
sub listPowers {
    my $self = shift;
    map {print $_} @{$self->powers()};
}

qntm
Jun 17, 2009

Roseo posted:

Oh, and think about this. You don't need intermediate scalars.

code:
sub addPower {
    my $self = shift;
    my %params = @_;

    $self->powers([@{$self->powers()}, Power->new(%params)]);
}
 
sub listPowers {
    my $self = shift;
    map {print $_} @{$self->powers()};
}

Honestly, I preferred it with intermediate scalars, because I find this very difficult to read and understand.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
It's also a good bit easier to run through in a debugger like Komodo.

Kidane
Dec 15, 2004

DANGER TO MANIFOLD

syphon posted:

Ok, so how do I loop over each array element and access that data? Running "print $array->[0]->{CLOCKSPEED};" does indeed output '2400 MHz', but running
code:
for (@{$Processors}) 
  { 
    print $Processors->[$_]->{CLOCKSPEED}; 
  }
outputs an infinite loop of "2400 MHz", even though the array only has 2 elements.

code:
foreach my $cpu (@{$processors}) {
    foreach my $cpu_param (keys %$cpu) {
        print $cpu_param, ': ', $cpu->{$cpu_param}, "\n";
    }
    print "\n";
}
Not checked for syntax at all, sorry.

Edit: didn't realize how many replies there were, my bad. :doh:

EVGA Longoria
Dec 25, 2005

Let's go exploring!

Roseo posted:

Oh, and think about this. You don't need intermediate scalars.

code:
sub addPower {
    my $self = shift;
    my %params = @_;

    $self->powers([@{$self->powers()}, Power->new(%params)]);
}
 
sub listPowers {
    my $self = shift;
    map {print $_} @{$self->powers()};
}

It was kind of making GBS threads itself without the scalars before, but yeah, I come from a background of more Python and scripting, I'm used to making each line do one thing and making it clear and simple code.

But thanks, I see what you mean and I'll fix it when I get home.

Is there a decent write up anywhere on making things a webapp in Perl? I was considering something along the lines of Titanium since it's supposedly pretty lightweight. Google's mostly been extolling the virtues of each without going into the process.

For anyone interested (and nerdy enough), the goal is to write a web-based combat tracker for the Heros/Champions gaming system.

Roseo
Jun 1, 2000
Forum Veteran

Casao posted:

It was kind of making GBS threads itself without the scalars before, but yeah, I come from a background of more Python and scripting, I'm used to making each line do one thing and making it clear and simple code.

But thanks, I see what you mean and I'll fix it when I get home.

Is there a decent write up anywhere on making things a webapp in Perl? I was considering something along the lines of Titanium since it's supposedly pretty lightweight. Google's mostly been extolling the virtues of each without going into the process.

For anyone interested (and nerdy enough), the goal is to write a web-based combat tracker for the Heros/Champions gaming system.

I'm going through http://advent.perldancer.org/2010 at the moment, which may fit the bill. It's also quite lightweight.

Also, one thing I was going to mention is that you don't need to writesubroutines for common tasks done to hashes, arrays, etc. Go through http://search.cpan.org/~drolsky/Moose-1.21/lib/Moose/Meta/Attribute/Native.pm.

code:
has 'powers' => [ is => 'rw', 
                  isa => 'ArrayRef',
                  default => sub { [] },
                  handles => [ addPower => push,
                               numPowers => count,
                               hasPowers => count,
                               mapPowers => map,
                             ]
                ];

sub printPowers {
    my $self = shift;
    $self->mapPowers( sub { print $_ } );
}

Roseo fucked around with this message at 04:26 on Dec 24, 2010

EVGA Longoria
Dec 25, 2005

Let's go exploring!

Roseo posted:

I'm going through http://advent.perldancer.org/2010 at the moment, which may fit the bill. It's also quite lightweight.

Also, one thing I was going to mention is that you don't need to writesubroutines for common tasks done to hashes, arrays, etc. Go through http://search.cpan.org/~drolsky/Moose-1.21/lib/Moose/Meta/Attribute/Native.pm.

code:
has 'powers => [ is => 'rw', 
                 isa => 'ArrayRef',
                 default => sub { [] },
                 handles => [ addPower => push,
                              numPowers => count,
                              hasPowers => count,
                              mapPowers => map,
                            ]
               ];

sub printPowers {
    my $self = shift;
    $self->mapPowers( sub { print $_ } );
}


Using that powers change, getting:

quote:

Cannot delegate addPower to push because the value of powers is not an object (got 'ARRAY(0x100b12808)') at ./Champion.pl line 11

Triggering it is:

code:
my $windwalk = Power->new(name => 'Windwalker', const => '1', end => 2);

$hero->addPower($windwalk);
Works the same if I pass it the parameters directly, instead of using the powers object.

Any idea why my created object is coming off as an array?

Roseo
Jun 1, 2000
Forum Veteran

Casao posted:

Using that powers change, getting:


Triggering it is:

code:
my $windwalk = Power->new(name => 'Windwalker', const => '1', end => 2);

$hero->addPower($windwalk);
Works the same if I pass it the parameters directly, instead of using the powers object.

Any idea why my created object is coming off as an array?

Add traits => ['Array'], to the powers declaration and see if that fixes it, sorry about that. I haven't done too much actual code with it, most of my experience is from the MooseX extension that became this (they transferred it from an extension into the core as it was so useful, but switched up the API somewhat)

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Native traits are nearly as cool as Moose itself, inlining them was a great idea.

EVGA Longoria
Dec 25, 2005

Let's go exploring!

Roseo posted:

Add traits => ['Array'], to the powers declaration and see if that fixes it, sorry about that. I haven't done too much actual code with it, most of my experience is from the MooseX extension that became this (they transferred it from an extension into the core as it was so useful, but switched up the API somewhat)

That got me there, thanks.

And thanks for the Dancer thing, looks nearly perfect, and good walkthrough. This should do nicely.

anagramarye
Jan 2, 2008

Array Age Man
So I'm working on a fairly simple thing, but I've run into the terrifying bugaboo of regexps. (All of the following is using single-line mode, since I'm only really worried about separating out broad sections chunk-by-chunk from the formatted text files I'm working with.)

The files I'm trying to read have a fairly standard format, with an intro ID number and name, a small block detailing general info about the file, an arbitrary number of PARTs, and then a marker for the end of the file. Kind of like:
pre:
			SECTION 12345

			SOMETHING SOMETHING

** Blah blah blah blah blah blah.

PART 1  SOMETHING
1.1  SOMETHING SOMETHING
     A. Something

PART 2  SOMETHING
2.1  SOMETHING SOMETHING
     A. Something

			END OF SECTION
Right now, I'm using this chunk below as a starting point (having already opened the file, gotten its contents, etc), which seems like it should work (spacing added to break tables less):

code:
my @regex_results =
     ($raw_text =~
          /^\s*SECTION (\d+)\s+([\w\s]+?)\n\s+(\*(.*?))(PART (\d+)  ([\w\s]+?)\n(.*?))+END OF SECTION\s*$/s
     );
The weirdness I'm running into is that it processes things like I want but skips over any intervening PART sections, only actually capturing the last PART in the file (like for that example I gave, only capturing PART 2, and not capturing PART 1 at all, despite having captured the number/name/intro text of the file), and my brain is too melted to figure out how to make my regex work how I want it to (capturing PART number / name / contents repeatedly). Anybody willing to point out what I'm doing wrong? :downs:

EDIT: As is often the way with these things, figuring out how to describe the problem made me think of a whole new angle to attack it from, and now doing that, I think I've figured out a completely different way to do what I want that's working better. :doh:

anagramarye fucked around with this message at 13:53 on Dec 29, 2010

The Gate of Nanna
Sep 20, 2008

:c00l: My Editor :c00l:
I found as a general good idea kind of rule, that when regexps get really long there is probably a better way to do it by breaking it down. Since the format is fairly standard you could use multiple regexps according to which section you're processing.

anagramarye
Jan 2, 2008

Array Age Man

The Gate of Nanna posted:

I found as a general good idea kind of rule, that when regexps get really long there is probably a better way to do it by breaking it down. Since the format is fairly standard you could use multiple regexps according to which section you're processing.

Yeah, I realized that like five minutes after I posted that, and switched to a recursive thing that's working way easier. My problems now are coming from the people who formatted the original text files having been 90% consistent but not having gone that last 10% at all :suicide:

Adbot
ADBOT LOVES YOU

Rohaq
Aug 11, 2006
Just a note for the future, a better way to write out regex questions in my mind is to do the following:

This is the data I'm parsing:
code:
			SECTION 12345

			SOMETHING SOMETHING

** Blah blah blah blah blah blah.

PART 1  SOMETHING
1.1  SOMETHING SOMETHING
     A. Something

PART 2  SOMETHING
2.1  SOMETHING SOMETHING
     A. Something

			END OF SECTION
And this is what I want to turn it into:
code:
[
  '12345',
  'SOMETHING SOMETHING',
  'Blah blah blah blah blah blah.',
  [
    'PART 1  SOMETHING',
    '1.1  SOMETHING SOMETHING',
    'A. Something'
  ],
  [
    'PART 2  SOMETHING',
    '2.1  SOMETHING SOMETHING',
    'A. Something'
  ]
]
Basically give us the example data, and give us an idea of what you want the final data structure to look with your example data. Having a regex that long, especially one that doesn't quite do what you want, makes it difficult to discern how you want to parse the data, and how you want it to end up.

I'm also more of a fan of a hash as storage when it comes to parsing out multiple values of data from raw text; it's far easier to pull out the data values you want from a hash than trying to remember the array position for the particular text you wanted, especially if your regex falls over with some data, and ends up populating the array incorrectly with odd data that caused an accidental match in your regex: It makes it far easier to spot in Perl's debugger when you can see that $regex_results['section_num'] contains incorrect data, rather than remembering what $regex_results[5] is for.

  • Locked thread