spill has asked for the wisdom of the Perl Monks concerning the following question:

I have been working on parsing ipconfig output from windows boxes and I think I finally have a good method for grabbing the info. My problem now is printing out the results. Here is my code so far.

#!/usr/bin/perl -w use Class::Struct; my $HostID = "0"; struct Adapter => { ip => '$', mac => '$', }; struct Host => { hostid => '$', hostname => '$', interface => '@', }; while (<STDIN>) { s/\r|\n//g; if ( /Host Name.*?:\s*(.*)/ ) { $c = Host->new(); $c->hostid($HostID); $c->hostname($1); printf ("hostid = %s\n", $c->hostid); printf ("hostname = %s\n", $c->hostname); $HostID++; } if ( / adapter/ ) { while (<STDIN>) { s/\r|\n//g; if ( /Physical Address.*?:\s*(.*)/ ) { $a=Adapter->new(); $a->mac($1); push @{$c->interface}, $a; printf ("Adapter = %s\n", $c->interface(0)->mac); if ($c->interface(1)) { printf ("Adapter = %s\n", $c->interface(1)->mac); } if ($c->interface(2)) { printf ("Adapter = %s\n", $c->interface(2)->mac); } } if ( /Lease Expires.*?:\s*(.*)/ ) { last; } } }

To troubleshoot, I added print lines after I put the data into the struct. My data is making it in, but I am having difficulty pulling it out after the while loop is complete. In addition to the Host struct, I also need to loop through the Adapters for each host. I have been trying to use foreach, but have been only been able to print the HASH or ARRAY address. I can't find a good example of a loop to read all the structs, any ideas? Here is the file I am reading from.

IP Config Windows IP Configuration Host Name . . . . . . . . . . . . : axter-win2003 Primary Dns Suffix . . . . . . . : Axter2.home Node Type . . . . . . . . . . . . : Hybrid IP Routing Enabled. . . . . . . . : No WINS Proxy Enabled. . . . . . . . : No DNS Suffix Search List. . . . . . : Axter2.home brnmll01.nj.comcast.net Ethernet adapter Local Area Connection: Connection-specific DNS Suffix . : brnmll01.nj.comcast.net Description . . . . . . . . . . . : SMC EtherPower II 10/100 Etherne +t Adapter Physical Address. . . . . . . . . : 00-E0-29-0A-F5-E2 DHCP Enabled. . . . . . . . . . . : Yes Autoconfiguration Enabled . . . . : Yes IP Address. . . . . . . . . . . . : 192.168.0.6 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 192.168.0.1 DHCP Server . . . . . . . . . . . : 192.168.0.1 DNS Servers . . . . . . . . . . . : 127.0.0.1 192.168.0.1 Lease Obtained. . . . . . . . . . : Tuesday, September 16, 2003 6:18 +:13 PM Lease Expires . . . . . . . . . . : Friday, September 19, 2003 6:18: +13 PM ipconfig completed IP Config Windows 98 IP Configuration Host Name . . . . . . . . . : LAPTOP.no.cox.net DNS Servers . . . . . . . . : 205.152.132.235 181.171.2.200 10.10.10.1 Node Type . . . . . . . . . : Broadcast NetBIOS Scope ID. . . . . . : IP Routing Enabled. . . . . : No WINS Proxy Enabled. . . . . : No NetBIOS Resolution Uses DNS : No 0 Ethernet adapter : Description . . . . . . . . : PPP Adapter. Physical Address. . . . . . : 44-45-53-54-00-00 DHCP Enabled. . . . . . . . : Yes IP Address. . . . . . . . . : 181.171.2.147 Subnet Mask . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . : 181.171.2.147 DHCP Server . . . . . . . . : 255.255.255.255 Primary WINS Server . . . . : Secondary WINS Server . . . : Lease Obtained. . . . . . . : 01 01 80 12:00:00 AM Lease Expires . . . . . . . : 01 01 80 12:00:00 AM 1 Ethernet adapter : Description . . . . . . . . : PPP Adapter. Physical Address. . . . . . : 44-45-53-54-00-01 DHCP Enabled. . . . . . . . : Yes IP Address. . . . . . . . . : 0.0.0.0 Subnet Mask . . . . . . . . : 0.0.0.0 Default Gateway . . . . . . : DHCP Server . . . . . . . . : 255.255.255.255 Primary WINS Server . . . . : Secondary WINS Server . . . : Lease Obtained. . . . . . . : Lease Expires . . . . . . . : 2 Ethernet adapter : Description . . . . . . . . : D-Link AIRPLUS Wireless LAN Adapter Physical Address. . . . . . : 00-80-C8-B5-76-1F DHCP Enabled. . . . . . . . : Yes IP Address. . . . . . . . . : 10.10.10.104 Subnet Mask . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . : 10.10.10.1 DHCP Server . . . . . . . . : 10.10.10.1 Primary WINS Server . . . . : Secondary WINS Server . . . : Lease Obtained. . . . . . . : 06 19 03 2:51:53 PM Lease Expires . . . . . . . : 06 26 03 2:51:53 PM ipconfig completed

janitored by ybiC: Balanced <readmore> tags around code and sample input

Replies are listed 'Best First'.
Re: Having problems with class::struct
by tedrek (Pilgrim) on Dec 11, 2003 at 20:49 UTC

    You only are saving one host because every time you go through the outer while loop $c gets overwritten with the current host. You need to save each host as you find it.

    To loop over the entries you are on the right track with foreach you just need to dereference the arrays, something like this assuming you store your hosts in @Hosts.

    foreach my $host (@Hosts) { foreach my $if (@{$host->interface()}) { print $if->mac(), "\n"; print $if->ip(), "\n"; } } #Or for a specific host/interface print $Hosts[0]->interface(0)->mac(), "\n";
      Is a hash the best place to store my hosts?

        I don't know, it depends on what your planning on doing with them. My guess is an array is all you'll need.

Re: Having problems with class::struct
by jmanning2k (Pilgrim) on Dec 11, 2003 at 22:01 UTC

    Have you looked at the CPAN modules? Win32::IPConfig is an OO interface to the ipconfig data.

    Though if what you have works for what you need it for (and is working with the helpful suggestions already listed), then just stick with what you've got.

      You are correct in that the OP has code that meets dragonchild's First Criterion of Good Coding. However, I would actually argue that the OP should convert to Win32::IPConfig, for the following reasons:
      1. OP would learn more about the Win32:: namespace
      2. OP would learn why it is useful to use said namespace
      3. Maintainer(s) (which might include OP) won't have to deal with hand-rolled code (and the bugs that go with no peer review)
      4. If ipconfig changes (as it probably will), Win32::IPConfig will (should?) change with it
      5. Should ipconfig be different on different Win32 machines, Win32::IPConfig will (should?) handle that transparently

      Those reasons boil down to meeting the Second Criterion of Good Coding.

      1. Code should do what it needs to do.
      2. Code should be both easy and safe to modify.

      1. Code that meets #1, no matter how poorly written, is "good".
      2. Code that meets both #1 and #2 is "great".
      3. Code that meets #2, but not #1, is worthless.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.